You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

setTimeout何时开始倒计时?异步执行与定时器触发顺序疑问

setTimeout执行顺序疑问

调试代码

setTimeout(() => console.log('first'), 2000);
for (let i  = 0; i < 5000; i++) {
   console.log("printing...")
}
setTimeout(() => console.log('second'), 1000);

预期执行逻辑(认为setTimeout立即开始倒计时)

  • 第一个setTimeout执行并启动2000ms定时器,由于其回调为异步执行,需等待调用栈清空后才会进入回调队列。
  • 执行for循环,在我的设备上耗时约20秒,期间第一个setTimeout的定时器应已完成倒计时。
  • 第二个setTimeout执行并启动1000ms定时器,逻辑同第一步。
  • 调用栈清空后处理回调队列,因第一个setTimeout先完成倒计时,应先输出'first'再输出'second'。

实际执行结果

printing...
/* 大量"printing..."输出 */
printing...
second
first

问题解答

不是的,setTimeout的定时器是在调用setTimeout函数的那一刻就开始计时,而非等初始代码执行完成后才启动。

你看到的结果核心原因是:你的for循环实际耗时远小于你估算的20秒(大概率是估算误差)。举个具体例子,假设for循环实际仅耗时0.5秒:

  • 第0秒:调用第一个setTimeout,启动2000ms定时器(将在第2秒到期)。
  • 第0-0.5秒:执行for循环,输出所有"printing..."。
  • 第0.5秒:调用第二个setTimeout,启动1000ms定时器(将在第1.5秒到期)。
  • 第0.5秒后:初始代码执行完毕,调用栈清空,事件循环开始等待任务。
  • 第1.5秒:第二个定时器到期,其回调被加入宏任务队列,事件循环处理它,输出"second"。
  • 第2秒:第一个定时器到期,其回调被加入宏任务队列,事件循环处理它,输出"first"。

如果for循环真的耗时20秒,那第一个定时器会在第2秒就到期,回调进入宏任务队列等待。等20秒后for循环结束,调用第二个setTimeout启动1000ms定时器,此时调用栈清空,事件循环会先处理队列里已有的第一个回调,输出"first",然后等1秒后再处理第二个回调输出"second",结果就会和你的预期一致。

你可以给for循环加个计时验证实际耗时:

console.time('loop');
for (let i  = 0; i < 5000; i++) {
   console.log("printing...")
}
console.timeEnd('loop');

内容的提问来源于stack exchange,提问作者seeingstars

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 21:47:09