setTimeout 设置为 0 毫秒时在做什么?

IT技术 javascript settimeout
2021-01-13 20:09:09

在 JavaScript 中,setTimeout(callback, delay)表示“毫秒callback调用delay”。但如果delay0它应该立即调用callback吗?

我很困惑,因为我在运行以下代码时看到的内容:

setTimeout(function() { 
    console.log('AAA');
}, 0); // Call this in 0 milliseconds 

for (i = 0; i < 1000; i++) {
    console.log('BBB'); 
}
for (i = 0; i < 1000; i++) {
    console.log('CCC'); 
}
for (i = 0; i < 1000; i++) {
    console.log('DDD'); 
}
for (i = 0; i < 1000; i++) {
    console.log('EEE'); 
}

这会将以下内容记录到控制台:

控制台日志

我预计AAA会比这更早地看到记录。有时间console.log在应该立即调用的函数之前执行 4000 次其他调用

有人可以解释setTimeout当延迟设置为 0 毫秒时在做什么吗?

1个回答

一些有用的事实可能有助于澄清正在发生的事情:

  1. JavaScript 是单线程的。异步回调被分配到一个消息放置在消息队列中
  2. 当前没有代码正在执行时,事件循环轮询消息队列,请求处理(执行)队列中的下一条消息。
  3. setTimeout 在指定的延迟过后,将一条消息(提供回调)添加到此队列的末尾。

(注意:这意味着setTimeout调用中的延迟是不确定的;它是执行回调之前最小延迟。实际花费的时间取决于处理队列中它前面的任何消息所需的时间。)

那么如果延迟设置为 会发生什么0一条新消息会立即添加到队列中,并会在当前执行的代码完成且之前添加的所有消息都已处理后进行处理。

你的代码发生了什么

当你调用setTimeout

setTimeout(function() { 
    console.log('AAA');
}, 0);

...一条消息被添加到具有指定回调的队列中。其余的代码……

for (i = 0; i < 1000; i++) {
    console.log('BBB'); 
}
// etc.

...继续同步执行。完成后,事件循环会轮询消息队列以获取下一条消息,并找到带有setTimeout回调的消息,然后对其进行处理(运行回调)。

回调只会在当前执行的代码完成才会执行,无论需要多长时间。

进一步阅读

有关事件循环的更多详细信息,请参阅:

“(注意:这意味着 setTimeout 调用中的延迟是不确定的……)”我从未考虑过这一点。谢谢你指出!
2021-03-13 20:09:09
漂亮而简洁的答案,给出了一个很好的初步想法。到目前为止,我在信息/简洁配额方面找到的最好的这个主题。谢谢!
2021-04-09 20:09:09