2012-03-29 60 views
2

我有点困惑如何确定何时称为异步函数多次从另一个完成对最后一个迭代的电话:的jQuery JavaScript的嵌套异步函数回调

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中的异步函数时没有掌握事件的顺序......请解释如何正常实现主题。

回答

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(); 
};​ 
+0

我已经简化了我的代码,将这个对我来说还是工作? – Tsar 2012-03-29 15:06:47

+0

是的,这仍然有效。给我一点,我会转换你的新代码... – 2012-03-29 15:16:53

+0

@Tsar看到我的编辑 – 2012-03-29 16:17:58

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

或使用'$ .each(数据,函数(索引,项目){...})' – 2012-03-29 14:15:57

+0

如果你想用其他几百个命令膨胀代码,没有很好的理由,当然,敲你自己... – 2012-03-29 14:20:30

+0

假设你指的是jQuery,OP已经在使用它(他包含标签),所以他可以免费获得'each',我个人认为它更具可读性。点虽然 – 2012-03-29 14:33:05