通常,我會使用傳遞給'jQuery.getJSON'函數的回調函數在服務器響應後執行某些操作。在這種情況下,我在某些輸入元素上應用了事件處理程序,但這些處理程序只應在多個Ajax請求成功後才執行。基本上我需要暫停事件處理程序的執行,直到我期望的某些數據可用。如何同步JavaScript代碼,這取決於多個Ajax請求的響應?
在多線程語言中,我會使用互斥鎖/信號量來做到這一點,但由於JavaScript是單線程的,我不知道這樣的事情是否可能。
通常,我會使用傳遞給'jQuery.getJSON'函數的回調函數在服務器響應後執行某些操作。在這種情況下,我在某些輸入元素上應用了事件處理程序,但這些處理程序只應在多個Ajax請求成功後才執行。基本上我需要暫停事件處理程序的執行,直到我期望的某些數據可用。如何同步JavaScript代碼,這取決於多個Ajax請求的響應?
在多線程語言中,我會使用互斥鎖/信號量來做到這一點,但由於JavaScript是單線程的,我不知道這樣的事情是否可能。
一個手動的方式來做到這一點是要排隊的AJAX數組中的調用,然後計算您收到的回覆的數量,並等待該計數與原始隊列的大小相匹配(或者,在響應完成時將呼叫從隊列中彈出,並且您知道在隊列大小爲0)。
你將不得不檢查你是否準備好繼續setTimeout調用。
或者,您可以在jQuery的退房遞延支持1.5+
編輯:手動方法的快速和骯髒的例子:
var remoteCallA = function(){
$.getJSON('someurl', function(){
success++;
});
};
var remoteCallB = function(){
// etc
};
var whenAllDone = function(){
// do something when everything is done
};
var checkAllDone = function(){
if(success === remoteCalls.length){
whenAllDone();
}
else{
setTimeout(checkAllDone, 1000);
}
};
var remoteCalls = [remoteCallA, remoteCallB];
var success = 0;
for(var i = 0, length = remoteCalls.length; i++){
remoteCalls[i]();
}
checkAllDone();
javascript是基於事件的,所以一種方法是在每次協調xhr得到響應時拋出一個事件。事件處理程序跟蹤響應,並且只有在全部返回時纔會繼續。
或者你也可以做同樣的事情,而不活動,只要直接調用的方法和協調在那裏的答覆....
我可以給你一個骯髒的解決方案。一旦所有查詢返回,創建你想要執行的函數。創建另一個函數來執行調度。就像信號/互斥一樣,創建一個「同步」變量。增加每個呼叫的變量。然後,在調度函數中,遞減變量,如果爲零,則執行所需的函數。將調度函數應用爲ajax返回的事件處理程序(如果您已有處理程序,而您不需要要暫停,請將其放在每個現有處理程序的末尾)。
然後,想一個更優雅的解決方案。
嗯,我感興趣的'setTimeout'功能可能是我需要的。在你給出的例子中,假設你使用了一個小超時(比如20毫秒),這個遞歸會不會變得太深?它可能會導致堆棧溢出。 – 2011-05-20 18:28:58
@Thiado這實際上並不是遞歸,因爲setTimeout()的調用會立即返回並退出函數。它只是告訴瀏覽器'嘿,在1000毫秒內運行'。 – Matt 2011-05-20 18:30:28
謝謝你,這正是我需要的:) – 2011-05-20 18:33:03