Javascript 带有阻塞代码的 setTimeout 行为
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14863022/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
setTimeout behaviour with blocking code
提问by Randomblue
This is my test code (fiddle here):
这是我的测试代码(在这里小提琴):
console.log('Before wait');
setTimeout(function () { console.log('Yo!'); }, 1000);
var start = Date.now();
while (Date.now() < start + 3000) {}
console.log('After wait');
This is the timeline of events in Chrome:
这是 Chrome 中事件的时间线:
- Time 0 seconds: Prints "Before wait"
- Time 3 seconds: Prints "After wait", and then immediately after "Yo!"
- 时间 0 秒:打印“等待前”
- 时间 3 秒:打印“After wait”,然后在“Yo!”之后立即打印
Is this behaviour according to spec? Why is it not
这种行为是否符合规范?为什么不是
- Time 0 seconds: Prints "Before wait"
- Time 3 seconds: Prints "After wait"
- Time 4 seoncds: Prints "Yo!"
- 时间 0 秒:打印“等待前”
- 时间 3 秒:打印“等待后”
- 时间 4 秒:打印“Yo!”
?
?
回答by Tomasz Nurkiewicz
JavaScript is single-threaded. If some block of code uses execution thread, no other code can be executed. This means your setTimeout()call must wait until main execution (the one with busy-waiting whileloop) finishes.
JavaScript 是单线程的。如果某个代码块使用执行线程,则不能执行其他代码。这意味着您的setTimeout()调用必须等到主执行(忙等待while循环)完成。
Here is what happens: you schedule setTimeout()to execute after a second and then block main thread for 3 seconds. This means the moment your busy loop finishes, timeout is already 2 seconds too late - and JS engine tries to keep up by calling your timeout as soon as possible - that is, immediately.
这是发生的事情:您安排setTimeout()在一秒后执行,然后阻塞主线程 3 秒。这意味着当您的繁忙循环完成时,超时已经晚了 2 秒 - 并且 JS 引擎试图通过尽快调用您的超时来跟上 - 即立即。
In fact this:
其实这个:
while (Date.now() < start + 3000) {}
is one of the worst things to do in JavaScript. You hold JavaScript execution thread for 3 seconds and no other event/callback can be executed. Typically browsers "freeze" in that period of time.
是 JavaScript 中最糟糕的事情之一。您持有 JavaScript 执行线程 3 秒钟,并且无法执行其他事件/回调。通常浏览器会在这段时间内“冻结”。
回答by tow
The delay of setTimeoutis relative to the exact point in time when it is called. It expires while you are still busy waiting. So it will be performed at the next instant where the control goes back into the event loop.
的延迟与setTimeout调用时的确切时间点有关。当您还在忙着等待时,它就会过期。因此它将在控制返回事件循环的下一个时刻执行。
Edit:
编辑:
The spec is a bit vague in this point, but I guess it's the intended and only straightforward interpretation:
规范在这一点上有点含糊,但我想这是有意且唯一直接的解释:
setTimeout(function, milliseconds)
This method calls the function once after a specified number of milliseconds elapses, until canceled by a call to clearTimeout. The methods returns a timerID which may be used in a subsequent call to clearTimeout to cancel the interval.
setTimeout(函数,毫秒)
此方法在经过指定的毫秒数后调用该函数一次,直到被调用 clearTimeout 取消。这些方法会返回一个 timerID,该 ID 可用于后续调用 clearTimeout 以取消间隔。
回答by Zoltán Tamási
When you run the busy-waiting loop after the setTimeout call, you don't let time for your "Yo!" to print out, because the Javascript runtime is busy with your loop (actualy the empty statement also makes it busy because of continues evaulaation of the loop condition).
当您在 setTimeout 调用后运行忙等待循环时,您不会为“哟!”留出时间。打印出来,因为 Javascript 运行时正忙于您的循环(实际上,由于循环条件的继续评估,空语句也使其忙碌)。
You should always avoid such a busy-waiting loop, because until that finishes, nothing else can be called or run in that window.
您应该始终避免这种忙等待循环,因为在该循环完成之前,在该窗口中不能调用或运行其他任何东西。

