2

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

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

我正在做的是调用谷歌距离矩阵服务,它有 25 个目的地的限制,因此我不得不拆分我的目的地数组来多次调用这个服务,但我不明白它什么时候完成。

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

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

4

3 回答 3

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();
};​
于 2012-03-29T13:51:38.877 回答
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);
}
于 2012-03-29T14:08:42.150 回答
0

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

于 2012-03-29T13:49:47.767 回答