2016-08-16 39 views
-1

我有一個小的JavaScript代碼,我試圖用setTimeout來等待某個外部輸入到達(通過responseReceived變量),或者等待最大閾值時間,然後退出。在setTimeout中調用的函數沒有被調用

下面的代碼:

var MAX_WAIT_THRESHOLD = 5000; 
var keepWaiting = true; 
var waitInterval = 500; 
var totalTimeWaited = 0; 

alert("Alert1"); 

while(keepWaiting == true) { 
    setTimeout(function() { 
    totalTimeWaited = totalTimeWaited + waitInterval; 
    alert("Alert2"); 
    if(responseReceived == true || totalTimeWaited >= MAX_WAIT_THRESHOLD) { 
     keepWaiting = false; 
    } 
    }, waitInterval); 
} 

的問題是由於某種原因setTimeout(..)從來沒有實際調用內創建匿名函數。我通過在Chrome的JavaScript執行控件中放置斷點來檢查這一點,並且執行永遠不會停留在放置在匿名函數內的任何斷點處。 JavaScript的執行在while ..行和setTimout(..)行之間不斷切換。代碼中的其他位置設置了responseReceived。另一種說法是,第一個警報顯示(警報1),但第二個警報從不顯示(警報2)。

我在做什麼錯?

編輯:

我通過報道的「重複」的問題去,但我看不出這是有關我的問題。我的問題不是關於while循環。而是關於爲什麼內部匿名函數沒有被調用。

+2

可能重複的[Javascript - 等到flag = true](http://stackoverflow.com/questions/22125865/javascript-wait-until-flag-true) –

+0

我不確定這個問題是如何連接到我問的那個。我知道JavaScript是單線程的。問題不在於while循環。問題在於內部匿名函數由於某種原因未被調用。 – Ahmad

+2

那是因爲你'while'循環永遠不會結束,所以你的計時器永遠不會有機會(單線程)。 –

回答

1

您的代碼殺死了我的瀏覽器選項卡。 :D

爲什麼不只是使用setInterval並擺脫while循環?

var MAX_WAIT_THRESHOLD = 5000; 
var waitInterval = 500; 
var totalTimeWaited = 0; 
var waiting = true; 

alert("Alert1"); 

var interval = setInterval(function() { 
    totalTimeWaited += waitInterval; 
    alert("Alert2"); 
    if (responseReceived || totalTimeWaited >= MAX_WAIT_THRESHOLD) { 
    // stop waiting 
    clearInterval(interval); 
    waiting = false; 
    alert("Done"); 
    } 
}, waitInterval); 
0

此問題與javascript concurrency model有關。

據我所知,所有的setTimeout回調只能在while循環結束後執行,因爲while循環是阻塞隊列的消息。但在這種情況下,它永遠不會結束。還有另一個SO線程解釋這一點,但我現在找不到它。

我看到你實際上是用控制變量來控制循環的最大時間。但是,由於此控制代碼在setTimeout回調中,因此在循環結束之前它不會被推入隊列中,因此控制var keepWaiting將永遠不會在循環內部變爲false。如果你把setTimeout函數之外的控制代碼,它不會打破瀏覽器會在某個時候顯示「警報2」的消息-several倍,在實況:

var MAX_WAIT_THRESHOLD = 5000; 
var keepWaiting = true; 
var waitInterval = 500; 
var totalTimeWaited = 0; 
var responseReceived = false; 

console.log("Alert1"); 

while(keepWaiting == true) { 
setTimeout(function() { 

console.log("Alert2"); 

}, waitInterval); 

    totalTimeWaited = totalTimeWaited + waitInterval; 
    if(responseReceived == true || totalTimeWaited >= MAX_WAIT_THRESHOLD) { 
    keepWaiting = false; 
    } 
} 

然而,所有的回調會由於之前暴露的原因,最終發生火災。

如果您想要setTimeouts的永恆循環,請使用遞歸而不是迭代。