jQuery JavaScript嵌套异步函数回调

时间:2012-03-29 13:44:29

标签: javascript jquery asynchronous jquery-callback

我有点困惑如何确定何时从另一个调用多次异步函数完成上一次迭代的调用:

function MainAsyncFunction(callback) {
  for (var i = 0; i < 10; i++) {
    SubAsyncFunction(function(success) {
      if (i >= 10 && success) { // THIS IS WRONG?!
        callback(true); // happens too early
      }
    });
  }
};

function SubAsyncFunction(callback) {
  SubSubAsyncFunction(function() {
        callback(true);
  });
}

我正在做的是调用Google Distance Matrix service,它有25个目的地的限制,因此我不得不分割我的目的地数组以多次调用此服务但我不明白它何时是结束。

在代码的主要部分我可以看出 MainAsyncFunction 中循环的第二次迭代在回调时尚未完成。

我认为我的问题是我在处理JavaScript中的异步函数时没有理解事件的顺序......请解释一下如何正常实现主题。

3 个答案:

答案 0 :(得分:7)

您可以使用jQuery Deferred对象,该对象充当表示异步操作状态的标记。

以下是一个简化示例:

//set up your sub method so that it returns a Deferred object
function doSomethingAsync() {
    var token = $.Deferred();
    myAsyncMethodThatTakesACallback(function() {
        //resolve the token once the async operation is complete
        token.resolve();
    });
    return token.promise();
};

//then keep a record of the tokens from the main function
function doSomethingAfterAllSubTasks() {
    var tokens = [];
    for (var i=0; i < 100; i++) {
        //store all the returned tokens
        tokens.push(doSomethingAsync());
    }

    $.when.apply($,tokens)
        .then(function() {
            //once ALL the sub operations are completed, this callback will be invoked
            alert("all async calls completed");
        });
};

以下是OP更新代码的更新版本:

function MainAsyncFunction(callback) {
  var subFunctionTokens = [];
  for (var i = 0; i < 10; i++) {
    subFunctionTokens.push(SubAsyncFunction());
  }

  $.when.apply($,subFunctionTokens)
  .then(function() {
    callback(true);
  });
};

function SubAsyncFunction() {
  var token = $.Deferred();
  SubSubAsyncFunction(function() {
        token.resolve();
  });
  return token.promise();
};​

答案 1 :(得分:0)

也许ajaxStop() event?这是一个jQuery事件,仅在完成所有活动的AJAX请求时触发。

答案 2 :(得分:0)

问题是i的值在循环中不断变化,最终在循环条件失败后超出界限。

解决此问题的最简单方法是:

for( i=0; i<5; i++) { // or whatever your loop is
    (function(i) {
        // the value of i is now "anchored" in this block.
    })(i);
}