2012-03-29 56 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