jQuery JavaScript嵌套异步函数回调

jQuery JavaScript Nested Asynchronous Functions callback

本文关键字:函数 回调 异步 嵌套 JavaScript jQuery      更新时间:2023-09-26

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

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中的异步函数时,我没有考虑到事件的顺序。。。请解释这个主题通常是如何实现的。

您可以使用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();
};​

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

问题是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);
}