2012-11-24 51 views
6

我有一些(可以說5)ajax請求,我通過使用jQuery.ajax函數在同一時間運行。jQuery ajax和「何時」功能

現在我想同步並彙總他們的結果,我使用jQuery.when函數來實現這一點。

我的問題是$.when只要其中一個請求失敗就會返回,並且即使他們成功,也會阻止其他人返回。

我該如何合併並獲得所有我的ajax請求的所有結果(那些失敗和那些成功)?

+1

這將有助於您發佈您的當前代碼.. – Nelson

回答

0

Working demo:http://jsbin.com/ocawoj/4/edit

function waitForAllPromisesToFinish() { 
    var i, 
     responses = [], 
     deferred = $.Deferred(), 
     helpers = { 
      addToResponses: function (index, data) { 
       responses[index] = data; 

       var i = 0, 
        isAnyNull = false; 

       for (i = 0; i < responses.length; i++) { 
        if (responses[i] === null) { 
         isAnyNull = true; 
         break; 
        } 
       } 

       if (isAnyNull === false) { 
        deferred.resolve(responses); 
       } 
      }, 
      setupPromise: function (promise, index) { 
       promise.always(function() { 
        var args = Array.prototype.slice.call(arguments); 
        helpers.addToResponses(index, args); 
       }); 
      } 
     }, 
     ajaxPromises = Array.prototype.slice.call(arguments); 

    for (i = 0; i < ajaxPromises.length; i++) { 
     responses[i] = null; 
    } 

    for (i = 0; i < ajaxPromises.length; i++) { 
     helpers.setupPromise(ajaxPromises[i], i); 
    } 

    return deferred.promise(); 
} 

函數返回一個promise。您附加了一個完成的處理程序,它與您提供給$ .when()的程序稍有不同。該函數記錄每個ajax承諾的響應。每當它發現所有ajax承諾都返回了數據,無論成功還是失敗,都將解決承諾。

雖然這是我首先想到的,但也可能有更高效的方法來達到同樣的效果。

+0

嗨!看來這正是我正在尋找的!但說實話,我暗中希望有更多的「標準」方式去做,因爲我認爲我不是第一個試圖解決這類問題的人。無論如何,感謝你的迴應和時間! :) –

+0

我剛剛瀏覽過'$ .when'的代碼,而且我所做的和'$ .when'非常類似。不同之處在於任何延遲失敗的時候'$ .when'調用'deferred.reject'。它確實有道理,否則你怎麼知道是否有任何延期失敗?您需要檢查每個延遲的resp,以確定它是否成功或失敗。你可以把它作爲錯誤跟蹤器的一張票,也許你可能會得到一些關於核心團隊如何認爲應該解決的反饋。 –

+0

我同意這不是一個錯誤,'$ .when'以這種方式工作,這是有道理的,沒關係。我認爲,這只是缺乏特徵,因爲在很多情況下,我們需要一種'whenAll'函數來同步所有結果,而不管它們是否成功。我不得不說,我很驚訝現在沒有這種可用的功能或解決方法(我之前稱之爲「標準」方式)。 –

0

您可以定義一個,兩個或三個更新功能(取決於你想要做什麼),其採取相應的承諾(AJAX回調)的響應:

function bindPromises(updateSuccess, updateFail, updateAnyway) { 
    var arrPromises = []; 

    // automate the promise retrieval if you want, that's up to you. 
    arrPromises[0] = ajaxRequest1(); 
    arrPromises[1] = ajaxRequest2(); 
    arrPromises[2] = ajaxRequest3(); 
    arrPromises[3] = ajaxRequest4(); 
    arrPromises[4] = ajaxRequest5(); 

    for(var j = 0; j < arrPromises.length; j++) { 
     arrPromises[j].then(updateSuccess, updateFail, updateAnyway); 
    } 
} 

或者,如果你想連自動化更多:

function bindPromises(arrayOfAjaxCalls, updateSuccess, updateFail, updateAnyway) { 
    var arrPromises = []; 

    for(var i = 0; i < arrayOfAjaxCalls.length; i++) { 
     arrPromises[i] = (arrayOfAjaxCalls[i])(); 
     arrPromises[i].then(updateSuccess, updateFail, updateAnyway); 
    } 
} 

如果你不熟悉的承諾,我想向您指出涉及該主題的一篇大文章:Understanding jQuery.Deferred and Promise

+0

嗨,糾正我,如果我錯了,但在我看來,你的代碼執行每個Ajax響應每個回調是不是?我所看到的是一種解決方案,即只有當所有請求完成時才執行一次方法(無論它們是否全部成功都無關緊要)。從這個方法我應該能夠得到所有的ajax調用響應(那些失敗和成功)。 –

+0

不,你說得對。但我並不確定你是否想等到所有的通話結束,或者在每次通話結束後決定採取一些行動。 顯然你現在有兩種方法的例子;) – nirazul