当我在 Firefox 和 Chrome 中运行这段代码时,结果是不同的:
function run() {
setTimeout(() => console.log("1"), 0);
setTimeout(() => console.log("2"), 100);
let start = Date.now();
while (Date.now() - start < 200) {
// do nothing
}
setTimeout(() => {
console.log("3");
}, 0);
start = Date.now();
while (Date.now() - start < 200) {
// do nothing
}
setTimeout(() => {
console.log("4");
}, 0);
}
run();
在 Chrome(和 Node.js)中,打印如下:1
3
2
4
在 Firefox 中,打印如下:1
2
3
4
但是如果我删除第 2 行( setTimeout(() => console.log("1"), 0);
),那么每个平台上都会打印相同的内容:2
3
4
如何解释这些不同的结果?谢谢!
最佳答案
解释:没关系。
何时将延迟的“消息”添加到事件循环消息队列中的细节是实现细节,而不是记录在案的保证。当您的函数将控制权交还给事件循环时,您所有的 setTimeout
call 有资格执行(其中三个计划立即运行,其中一个计划在 100 毫秒内运行),并且您已经保证自您安排它以来至少有 400 毫秒。
两者之间的区别可能很简单,就像他们是否选择在新项目插入之前或之后立即寻找已经准备好的延迟任务(从延迟队列移动到主“准备就绪”消息队列)主消息队列。 Chrome 选择在 3
之后立即移动已安排(因此 3
进入,然后是延迟的 2
),Firefox 紧接在之前(在 2
放入之前移入 3
)。
在不违反任何书面保证的情况下,它们都可以在下一个版本中进行更改。不要依赖它,不要期望它稳定。 While immediately scheduled tasks are guaranteed to execute in FIFO order , there are no guarantees on when deferred tasks get moved onto the "ready-to-go" message queue .规范似乎要求 1
, 3
和 4
按该顺序执行(因为它们都立即准备就绪,而不是延迟),只有 2
的顺序灵活,但即使这样也不是真正的保证; the various ways in which an "immediate" setTimeout
task may not actually be scheduled immediately 会变得很奇怪.
您可能对 why setTimeout
can take longer than expected 上的 MDN 文档感兴趣;它通过副作用解释了事件循环的许多工作原理,即使它仔细地不保证您正在探索的细节。
关于javascript - setTimeout 回调在 Firefox 和 Chrome 中的执行顺序不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72737324/