2011-05-20 22 views
0

通常,我會使用傳遞給'jQuery.getJSON'函數的回調函數在服務器響應後執行某些操作。在這種情況下,我在某些輸入元素上應用了事件處理程序,但這些處理程序只應在多個Ajax請求成功後才執行。基本上我需要暫停事件處理程序的執行,直到我期望的某些數據可用。如何同步JavaScript代碼,這取決於多個Ajax請求的響應?

在多線程語言中,我會使用互斥鎖/信號量來做到這一點,但由於JavaScript是單線程的,我不知道這樣的事情是否可能。

回答

1

一個手動的方式來做到這一點是要排隊的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(); 
+0

嗯,我感興趣的'setTimeout'功能可能是我需要的。在你給出的例子中,假設你使用了一個小超時(比如20毫秒),這個遞歸會不會變得太深?它可能會導致堆棧溢出。 – 2011-05-20 18:28:58

+0

@Thiado這實際上並不是遞歸,因爲setTimeout()的調用會立即返回並退出函數。它只是告訴瀏覽器'嘿,在1000毫秒內運行'。 – Matt 2011-05-20 18:30:28

+0

謝謝你,這正是我需要的:) – 2011-05-20 18:33:03

1

javascript是基於事件的,所以一種方法是在每次協調xhr得到響應時拋出一個事件。事件處理程序跟蹤響應,並且只有在全部返回時纔會繼續。

或者你也可以做同樣的事情,而不活動,只要直接調用的方法和協調在那裏的答覆....

1

我可以給你一個骯髒的解決方案。一旦所有查詢返回,創建你想要執行的函數。創建另一個函數來執行調度。就像信號/互斥一樣,創建一個「同步」變量。增加每個呼叫的變量。然後,在調度函數中,遞減變量,如果爲零,則執行所需的函數。將調度函數應用爲ajax返回的事件處理程序(如果您已有處理程序,而您不需要要暫停,請將其放在每個現有處理程序的末尾)。

然後,想一個更優雅的解決方案。