функция javascript дождаться завершения другой функции

У меня есть две функции javascript, которые вызываются из android. После долгих сеансов отладки, наконец, я понял, что проблема возникает из-за того, что вторая функция вызывается до завершения первой. Я уже искал примеры с deferred и т. д., но все они зависят от вызовов функций внутри другого.

function FunctInit(someVarible){ //someVariable is sent from android, cannot call again from getResult
//init and fill screen
}

function getResult(){ //also getResult need to be called from android via button
//return some variables
}

Как я могу заставить getResult ждать FuncInit? Есть ли способ добиться этого с помощью Javascript?


person tugce    schedule 09.07.2014    source источник
comment
Не могли бы вы установить флаг isInitialized и спать в getResult, если он еще не был перевернут?   -  person Andrew Walters    schedule 09.07.2014
comment
Выполняет ли FunctInit какое-то асинхронное действие, завершения которого вы также хотите дождаться?   -  person Paul S.    schedule 09.07.2014
comment
@ПолС. да, он также вызывает две функции, которые должны быть завершены до того, как getResult   -  person tugce    schedule 09.07.2014
comment
Вы можете прочитать материал о обратных вызовах. Посмотрите, например: recurial.com/programming/ сложный для понимания, но мощный, и, безусловно, хорошее решение для вашей проблемы.   -  person Lord Grosse Jeanine    schedule 09.07.2014
comment
Я надеюсь, что вы отметите ответ, поэтому я не хочу публиковать его здесь, см. здесь stackoverflow.com/questions/12116505/   -  person Anto King    schedule 09.07.2014
comment
@AntoKing пометил, потому что я четко указал в своем вопросе, что две функции вызываются через Android, они не должны вызывать друг друга в javascript.   -  person tugce    schedule 09.07.2014


Ответы (3)


На мой взгляд, отложенные/обещания (как вы упомянули) - это путь, а не использование тайм-аутов.

Вот пример, который я только что написал, чтобы продемонстрировать, как вы можете сделать это с помощью deferreds/ обещания.

Потратьте некоторое время, чтобы поиграть с deferred'ами. Как только вы действительно поймете их, станет очень легко выполнять асинхронные задачи.

Надеюсь это поможет!

$(function(){
    function1().done(function(){
        // function1 is done, we can now call function2
        console.log('function1 is done!');

        function2().done(function(){
            //function2 is done
            console.log('function2 is done!');
        });
    });
});

function function1(){
    var dfrd1 = $.Deferred();
    var dfrd2= $.Deferred();

    setTimeout(function(){
        // doing async stuff
        console.log('task 1 in function1 is done!');
        dfrd1.resolve();
    }, 1000);

    setTimeout(function(){
        // doing more async stuff
        console.log('task 2 in function1 is done!');
        dfrd2.resolve();
    }, 750);

    return $.when(dfrd1, dfrd2).done(function(){
        console.log('both tasks in function1 are done');
        // Both asyncs tasks are done
    }).promise();
}

function function2(){
    var dfrd1 = $.Deferred();
    setTimeout(function(){
        // doing async stuff
        console.log('task 1 in function2 is done!');
        dfrd1.resolve();
    }, 2000);
    return dfrd1.promise();
}
person Antoine Cloutier    schedule 09.07.2014
comment
Почему вы заключаете свои функции в $.when()? Нет необходимости. Вы можете просто сделать function1().done() - $.when() там вообще не нужно. $.when() используется, когда у вас есть несколько промисов, и вы хотите знать, когда они все будут выполнены, но вообще бесполезен, если передаете только одно промис. - person jfriend00; 09.07.2014
comment
Вы совершенно правы, сначала у меня было несколько обещаний, и я просто забыл удалить $.when. Я заметил это почти одновременно с вашим комментарием. Спасибо, что указали на это! - person Antoine Cloutier; 09.07.2014
comment
Большое спасибо за пример. Это очень хороший способ объяснить на простом примере @AntoineCloutier - person samsri; 18.09.2015
comment
Извините, я не очень понимаю, как это работает, поэтому я просто следую примеру. Когда я вызываю функцию с .done , я получаю сообщение об ошибке Невозможно прочитать свойство "done" из неопределенного. - person chourn solidet; 30.12.2016
comment
привет @AntoineCloutier Я не очень понимаю, что такое отложенный, но просто хочу знать, почему вы все еще используете тайм-аут вместо использования только отложенного? - person Fai Zal Dong; 11.08.2017
comment
@AntoineCloutier Это действительно хорошо написано и объяснено, я смог скопировать ваш пример, удалить тайм-ауты и заставить его работать идеально для нужного мне обработчика AJAX. Обычно я не буду комментировать вне контекста, но я хотел бы поблагодарить вас, так как теперь у меня есть очень четкое понимание того, как работают done(), resolve() и promise(), до вашего поста я был [keyword_stuff] цепочкой setTimeout к обрабатывать условия гонки (я никогда не буду делать это снова, видя, насколько это лениво). Спасибо. - person Christian Žagarskas; 31.05.2018
comment
@AntoineCloutier Можете ли вы взглянуть на этот вопрос stackoverflow.com/q/56397604/4425004 с этим текущим решением? - person Pranesh Janarthanan; 07.06.2019

Я могу придумать несколько способов сделать это.

Используйте обратный вызов:

 function FunctInit(someVarible){
      //init and fill screen
      AndroidCallGetResult();  // Enables Android button.
 }

 function getResult(){ // Called from Android button only after button is enabled
      //return some variables
 }

Используйте тайм-аут (это, вероятно, было бы моим предпочтением):

 var inited = false;
 function FunctInit(someVarible){
      //init and fill screen
      inited = true;
 }

 function getResult(){
      if (inited) {
           //return some variables
      } else {
           setTimeout(getResult, 250);
      }
 }

Подождите, пока произойдет инициализация:

 var inited = false;
 function FunctInit(someVarible){
      //init and fill screen
      inited = true;
 }

 function getResult(){
      var a = 1;
      do { a=1; }
      while(!inited);
      //return some variables
 }
person Nicholas    schedule 09.07.2014
comment
тайм-аут в моем случае не сработает, так как я полагаюсь на возврат функции javascript на Android. Но спасибо за ответ - person tugce; 10.07.2014

Следующий ответ может помочь в этой и других подобных ситуациях, таких как синхронный вызов AJAX -

Рабочий пример

waitForMe().then(function(intentsArr){
  console.log('Finally, I can execute!!!');
},
function(err){
  console.log('This is error message.');
})

function waitForMe(){
    // Returns promise
    console.log('Inside waitForMe');
    return new Promise(function(resolve, reject){
        if(true){ // Try changing to 'false'
            setTimeout(function(){
                console.log('waitForMe\'s function succeeded');
                resolve();
            }, 2500);
        }
        else{
            setTimeout(function(){
                console.log('waitForMe\'s else block failed');
                resolve();
            }, 2500);
        }
    });
}
person Sujit Kumar Singh    schedule 01.08.2017