[英]setTimeout behaviour with blocking code
這是我的測試代碼(在這里小提琴):
console.log('Before wait');
setTimeout(function () { console.log('Yo!'); }, 1000);
var start = Date.now();
while (Date.now() < start + 3000) {}
console.log('After wait');
這是 Chrome 中事件的時間線:
這種行為是否符合規范? 為什么不是
?
JavaScript 是單線程的。 如果某個代碼塊使用執行線程,則不能執行其他代碼。 這意味着您的setTimeout()
調用必須等到主執行(忙等待while
循環的那個)完成。
這是發生的事情:您安排setTimeout()
在一秒后執行,然后阻塞主線程 3 秒。 這意味着當您的繁忙循環完成時,超時已經晚了 2 秒 - 並且 JS 引擎試圖通過盡快調用您的超時來跟上 - 即立即。
其實這個:
while (Date.now() < start + 3000) {}
是 JavaScript 中最糟糕的事情之一。 您持有 JavaScript 執行線程 3 秒鍾,並且無法執行其他事件/回調。 通常瀏覽器會在這段時間內“凍結”。
setTimeout
的延遲與調用時的確切時間點有關。 當您還在忙着等待時,它就會過期。 因此它將在控制返回事件循環的下一個時刻執行。
編輯:
規范在這一點上有點含糊,但我想這是有意且唯一直接的解釋:
setTimeout(函數,毫秒)
此方法在經過指定的毫秒數后調用該函數一次,直到被調用 clearTimeout 取消。 這些方法會返回一個 timerID,該 ID 可用於后續調用 clearTimeout 以取消間隔。
當您在 setTimeout 調用后運行忙等待循環時,您不會為“喲!”留出時間。 打印出來,因為 Javascript 運行時正忙於您的循環(實際上,由於循環條件的繼續評估,空語句也使其忙碌)。
您應該始終避免這種忙等待循環,因為在該循環完成之前,在該窗口中不能調用或運行其他任何東西。
不確定它是否可以幫助您,但此問題已在以下位置進行了解釋: https : //developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#Run-to-completion
出於這個原因,第二個參數表示最短時間——而不是保證時間。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.