![](/img/trans.png)
[英]Why isn't a variable defined in for loop not visible in setTimeout function?
[英]Why isn't setTimeout cancelling my loop?
我想知道一個 JavaScript 的while
語句(在 Chrome 的控制台中)可以在一毫秒內增加一個變量多少次,所以我很快就把這個片段直接寫到了控制台中:
var run = true, i = 0;
setTimeout(function(){ run = false; }, 1);
while(run){ i++; }
問題是它永遠運行。
為什么會發生這種情況,我該如何解決?
這又回到了 JavaScript 1的單線程特性。 發生的事情幾乎是這樣的:
run = false
。 該計划目前的功能是運行(或任何其他當前活動)后運行。setTimeout()
回調將被執行並且run=false
。 如您所見, setTimeout()
方法在這里不起作用。 您可以通過檢查while
條件中的時間來解決這個問題,但這會干擾您的實際測量。
1至少出於更實際的目的,您可以將其視為單線程。 實際上有一個所謂的“事件循環”。 在該循環中,所有函數都會排隊,直到它們被執行。 如果您排隊一個新函數,它會被放置在該隊列中的相應位置。 當前功能完成之后,發動機將在下次函數從隊列(相對於作為引入的定時,例如,通過setTimeout()
並執行它。
結果在每個時間點只執行一個函數,從而使執行幾乎是單線程的。 事件有一些例外情況,在下面的鏈接中進行了討論。
以供參考:
https://stackoverflow.com/a/16757582/1169798
這里更詳細地解釋了類似的場景
https://stackoverflow.com/a/2734311/1169798
更深入地描述何時可以將 JS 視為單線程,何時不可以。
JavaScript 是單線程的,因此當您處於循環中時,不會執行任何其他操作。
為了保持Chrome的真實速度,而不必不斷檢索時間來計算速度,您可以嘗試以下JS代碼:
var start = new Date().getTime()
var i = 0
while(i<1000000)
{
i++
}
var end = new Date().getTime()
var delta = end-start
var speed = i/delta
console.log(speed + " loops per millisecond")
Javascript 是單線程的,這意味着它一次只按順序運行一條指令。
與許多其他語言和庫一樣,事件系統由事件循環處理。 事件循環基本上是一個循環,它在每次迭代時檢查隊列中的消息,並調度事件。
在 javascript 中(就像在實現這種模式的語言中一樣),當堆棧為空時,即所有函數都有返回時,換句話說,在程序代碼的末尾,將調用事件循環。
你的“真實”程序在幕后看起來像這樣:
var run = true, i = 0;
setTimeout(function(){ run = false; }, 1);
while(run){ i++; }
while(true) {
/*
* check for new messages in the queue and dispatch
* events if there are some
*/
processEvents();
}
因此,永遠不會處理來自時鍾的消息說超時結束。
關於事件循環的更多信息: https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/EventLoop
當然它有點復雜,請在此處查看這些示例: JavaScript 是否保證是單線程的? ( tl;dr:在一些瀏覽器引擎中,一些外部事件不依賴於事件循環,一旦發生就會立即觸發,搶占當前任務。但 setTimeout 不是這種情況,它只是向隊列中添加一條消息並且永遠不會立即開火。)
While 循環不訪問 setTimeout。 您有設置運行為真的代碼,然后它永遠不會變為假。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.