设置为0毫秒时setTimeout的作用是什么?

DDa*_*Dan 41 javascript settimeout

在JavaScript中,setTimeout(callback, delay)意思是" callbackdelay毫秒之后调用".但是如果delay是的话0呢?它应该立即打电话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'); 
}
Run Code Online (Sandbox Code Playgroud)

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

console_log

我希望看到AAA记录的速度要早得多.在console.log应该立即调用的函数之前,有时间执行4000个其他调用.

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

Jor*_*ray 63

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

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

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

那么如果将延迟设置为0?会发生什么?新消息立即添加到队列中,并在当前正在执行的代码完成并且已处理任何先前添加的消息时进行处理.

您的代码中发生了什么

当你调用setTimeout...

setTimeout(function() { 
    console.log('AAA');
}, 0);
Run Code Online (Sandbox Code Playgroud)

...使用指定的回调将消息添加到队列中.你的其余代码......

for (i = 0; i < 1000; i++) {
    console.log('BBB'); 
}
// etc.
Run Code Online (Sandbox Code Playgroud)

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

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

进一步阅读

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

  • *"(注意:这意味着setTimeout调用的延迟并不确定......)"*我从未考虑过这一点.谢谢你指出来! (3认同)
  • 简洁明了的答案给出了一个很好的初步想法。到目前为止,我在信息/简洁性配额方面找到的最好的方法。谢谢! (2认同)