等待另一个函数完成的JavaScript函数

14

我有两个在Android中被调用的JavaScript函数。经过长时间的调试,我终于意识到问题出在第二个函数在第一个函数完成之前被调用了。我已经搜索了关于延迟等方面的示例,但它们都依赖于函数在另一个函数内部调用。

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实现这种方式的方法?


你能否在getResult中设置一个isInitialized标志并休眠,如果它还没有被翻转吗? - Andrew Walters
1
FunctInit是否执行某些异步操作,您也希望等待其完成? - Paul S.
@PaulS。是的,它还调用了两个函数,在获取结果之前需要完成。 - tugce
1
你可能想要阅读关于“回调函数”的相关内容。例如,可以查看这个网址:http://recurial.com/programming/understanding-callback-functions-in-javascript/。虽然有些难以理解,但它是非常强大的,并且肯定是解决你问题的好方法。 - Lord Grosse Jeanine
希望您将答案记下,这样我就不必再在那里发布了。请参见此处:https://dev59.com/sGct5IYBdhLWcg3wZcqL - Anto king
@AntoKing被标记了,因为我在问题中明确指出了两个函数是通过Android调用的,它们不应该在JavaScript内相互调用。 - tugce
3个回答

47

在我看来,延迟对象/承诺(正如您所提到的)是走的正确之路,而不是使用超时。

这里有一个我刚写的示例,演示了如何使用延迟对象/承诺实现它。

花些时间来玩弄一下延迟对象。一旦你真正理解了它们,执行异步任务就变得非常容易。

希望这能帮助到你!

$(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();
}

为什么要在函数中包装$.when()?其实没有必要。你可以直接使用function1().done(),根本不需要使用$.when()。当你有多个promises并想知道它们何时全部完成时才需要使用$.when(),但如果只传递一个promise,它就没有任何用处。 - jfriend00
你非常正确,一开始我有多个承诺,只是忘记移除 $.when。我在你评论的同时注意到了这一点。感谢指出! - Antoine Cloutier
非常感谢您提供的示例。通过简单的示例进行解释是一个非常好的方法。@AntoineCloutier - samsri
1
很抱歉,我不太理解它的工作原理,所以我只是按照示例进行操作。当我使用 .done 调用函数时,出现了“无法读取未定义属性 'done'”的错误。 - chourn solidet
1
嗨@AntoineCloutier,我不是很理解deferred,但我想知道为什么你仍然使用timeout而不是仅使用deferred? - Fai Zal Dong
显示剩余2条评论

6
我可以想到几种方法来做这件事。

使用回调函数:

 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
 }

超时设置在我的情况下不起作用,因为我依赖于 Android 上 JavaScript 函数的返回值。但是,感谢您的答案。 - tugce

2
以下答案可以帮助您解决此类问题,例如同步 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);
        }
    });
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接