2013-01-22 61 views
15

我有多個ajax查詢同時運行,我希望他們等待最後一個返回,然後在所有ajax上運行成功處理程序調用。舉個簡單的例子,考慮:多個ajax調用等待最後一個加載,然後執行

$.ajax({//ajax call 1 
    url:page1.php, 
    success: function(data1){ 
     //do something with data1 
    } 
}); 

.... 

$.ajax({//ajax call 2 
    url:page2.php, 
    success: function(data2){ 
     //do something with data2 
    } 
}); 
//consider more than just two concurrent requests 

假設所有的請求都是同時發送的。由於它們是異步的,它們將在不同的時間返回。假設一個請求需要100ms才能返回,另一個請求需要3000毫秒才能返回。我顯然不知道哪一個會首先或最後返回。他們都以某種方式更新了DOM,我希望在一次更新時一次性向觀看者顯示所做的更改。我該怎麼做呢?

我能想到的最好的辦法是將data1和data2保存爲全局變量。然後每次返回成功時都有一個計數器變量。然後,在計數器== TOTAL_NUM_REQUESTS中調用像updateAll()這樣的函數,然後遍歷所有全局變量並將它們放在需要去的地方。但這似乎很混亂,容易出錯。另外,這將是很多全局變量。

我最想要的是讓成功處理程序在返回時睡覺,然後根據我的條件將所有人作爲返回值發送,然後向所有人發送喚醒消息,然後可以繼續執行。這似乎是最乾淨的,但我沒有意識到在javascriptland中有這樣的功能。

有沒有人對此有任何的意見?

答案更新

感謝李下面,我是能夠得到解決。我的解決方案看起來類似於他的下面我建立了一個async分配給$ .ajax調用的變量列表。最初,這些ajax調用的成功處理程序仍然被調用,所以我刪除了它們,並將它們放入另一個函數中,隨後將由我編寫的這個when塊調用。我在像這樣的函數傳遞results

var results = []; 
results.push(async1); 
results.push(async2); 
... for all the results ... 

$.when.apply(this, results).done(function() { 
    for(var i=0;i<arguments.length;i++){ 
    dataobject=arguments[i][0] 
    if(dataobject.variousattribute) 
     mySuccessHandlerFirstGuy(dataobject) 
    else if(dataobject.anotherattribute) 
     mySuccessHandlerSecondGuy(dataobject) 
     //etc .... 
    } 
}; 

的參數對象採取了一些工作來弄清楚它是什麼。這是一個二維數組(列表清單)。第一個索引表示與給定的ajax請求對應的返回對象。它似乎是爲了順序,但最好讓你的服務器返回一些你可以查找並相應地寫一個if/else塊的東西。然後,在那個給定的元素中,該列表中似乎有3個元素。第一個是從服務器返回的值,即你想要的值。第二個總是一個字符串success,你可以用它來檢查這個調用是否工作。而該列表中的第三個元素似乎是最初的請求(儘管我不確定)。這對我來說沒用。

無論如何,我希望這有助於未來的某個人。並再次感謝李指出我正確的方向。

+0

的可能的複製後emptycallback將被稱爲[等到所有的jQuery Ajax請求都完成了嗎?](https://stackoverflow.com/questions/3709597/wait-until-all-jquery-ajax-requests-are-done) – cilf

回答

32

使用jQuery $。()函數時運行的東西時,所有的Ajax調用完成:

jQuery.when docs

var async1 = $.ajax({//ajax call 1 
    url:page1.php, 
    success: function(data1){ 
     //do something with data1 
    } 
}); 

.... 

var async2 = $.ajax({//ajax call 2 
    url:page2.php, 
    success: function(data2){ 
     //do something with data2 
    } 
}); 

$.when(async2, async1).done(function(result2, result1) { 
    ... do this when both are successful ... 
}); 

添加在回答問題:

如果你有一堆的Ajax調用,您可以使用「應用'像這樣:

var results = []; 
results.push(async1); 
results.push(async2); 
... for all the results ... 

$.when.apply(this, results).done(function() { 
    ... use 'arguments' array to get results ... 
}); 
+0

不錯,不知道,首先在我腦海中調用的是http://api.jquery.com/category/deferred-object/ – dmi3y

+0

'當'只是在所有參數上建立一個新的延遲正常的延遲方法起作用。唯一棘手的部分是,當第一個失敗並且其他可能不完整時它失敗。 '完成'只有全部成功纔會執行。 (就像'失敗'是一個'或','成功'是一個'和')。 –

+0

這看起來很有前途,'var async1'必須是全局範圍的,對吧? – Landon

0

這可能可以做到與你已經提出的非常類似的方式編輯。

首先,創建全局變量var sleep = truevar request_count = 0。然後啓動一個計時器,每秒鐘檢查request_count的請求總數。然後,您的成功功能可以增加request_counter,然後開始循環,直到sleep == false。然後,當通過定時器運行的監控功能檢測到request_count == TOTAL_REQUESTS時,它會設置sleep = false,並且當時您的所有成功功能都會繼續存在。

+0

你能澄清你的意思嗎?循環到sleep == false?像一個繁忙的循環?你的意思是像'while(request_count Landon

+1

是的,那基本上就是我的建議。但是你是對的,如果你能避免它會更好,而且看起來李的建議是正確的路要走。 –

0

一個簡單的解決方案將使用PreloaderQ模塊

https://www.npmjs.com/package/preloaderq

使用如下

var preloader = new PreloaderQ() 
preloader.setEmptyCallback(function(){ 
    //all tasks are finished 
}) 

preloader.setFirstTaskCallback(function(){ 
    //started first task 
}) 

preloader.enqueueTask('ajax1') 

$.ajax({//ajax call 1 
    url:page1.php, 
    success: function(data1){ 
     prealoader.dequeueTask('ajax1') 
     //do something with data1 
    } 
}); 

preloader.enqueueTask('ajax2') 

$.ajax({//ajax call 1 
    url:page2.php, 
    success: function(data2){ 
     prealoader.dequeueTask('ajax2') 
     //do something with data2 
    } 
}); 

兩者都完成

相關問題