为什么setTimeout输出不按顺序添加的数字

Why setTimeout outputs numbers not in order added

本文关键字:添加 数字 顺序 setTimeout 输出 为什么      更新时间:2024-01-22

我有以下代码:

function wait(ms) {
    var start = +(new Date());
    while (new Date() - start < ms);
}
(function() {
    setTimeout(function(){console.log(2)}, 1000);
    setTimeout(function(){console.log(3)}, 0);
    setTimeout(function(){console.log(4)}, 0);
    wait(2000); //!!! blocking events processing here
})();

它输出:

3
4
2

我在某个地方读到setTimeout将函数添加到事件队列中,然后当这个函数是链中的第一个函数时,它会检查是否已经过了指定的时间量,如果没有,它会推迟执行。在这种逻辑下,我期望上面的代码输出:2,3,4,因为wait()函数阻止了事件链接处理,调用堆栈完成,浏览器终于有时间处理通过setTimeout添加的函数,所以所有三个函数都按添加的顺序放在队列中,第一个函数已经通过了1000,所以浏览器可以接受它并执行,但是它等待第二个和第三个添加的功能。为什么?我的逻辑错误在哪里?

回调函数在超时后进入队列。所以,

setTimeout(function(){console.log(3)}, 0);
setTimeout(function(){console.log(4)}, 0);

立即进入,但

setTimeout(function(){console.log(2)}, 1000);

1秒后进入队列。因此订单3,4,2

来自MDN:

调用setTimeout将在作为第二个参数传递的时间之后向队列添加一条消息。如果队列中没有其他消息,则会立即处理该消息;但是,如果有消息,setTimeout消息将不得不等待其他消息被处理。因此,第二个参数表示最短时间,而不是保证时间。

emphasis mine