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

JavaScript异步任务执行顺序:Promise与setTimeout代码输出分析

JavaScript代码执行顺序解析

代码示例

function job(){
    sequenceB()
    sequenceC()
}

function sequenceB(){
    setTimeout(_ => console.log(`🍅 Timeout at B`), 0);
    Promise.resolve().then(_ => console.log('🍍 Promise at B'));
}

function sequenceC(){
    setTimeout(_ => console.log(`🍅 Timeout at C`), 0);
    Promise.resolve().then(_ => setTimeout(console.log('🍍 Promise at C'), 1000));
}
job();

实际输出顺序

🍍 Promise at B → 🍍 Promise at C → 🍅 Timeout at B → 🍅 Timeout at C

执行逻辑说明

JavaScript的执行依赖事件循环机制,任务分为两类,优先级有明确差异:

  • 宏任务:包括setTimeout、setInterval、I/O操作等,任务队列中的宏任务会按顺序执行,每次执行完一个宏任务后会先清空所有微任务。
  • 微任务:包括Promise的then/catch/finally回调等,优先级高于宏任务,当前宏任务执行完毕后会立即处理所有微任务。

具体执行步骤:

  1. 同步代码执行阶段

    • 调用job(),先执行sequenceB():
      • 调用setTimeout,将回调_ => console.log('🍅 Timeout at B')加入宏任务队列。
      • 调用Promise.resolve(),将then的回调_ => console.log('🍍 Promise at B')加入微任务队列。
    • 接着执行sequenceC():
      • 调用setTimeout,将回调_ => console.log('🍅 Timeout at C')加入宏任务队列。
      • 调用Promise.resolve(),将then的回调_ => setTimeout(console.log('🍍 Promise at C'), 1000)加入微任务队列。
  2. 微任务处理阶段

    • 同步代码执行完后,优先处理微任务队列:
      • 第一个微任务:执行sequenceB的then回调,直接输出🍍 Promise at B。
      • 第二个微任务:执行sequenceC的then回调,这里注意:setTimeout的第一个参数是console.log('🍍 Promise at C'),这是立即执行的函数调用(而非延迟执行的回调),所以直接输出🍍 Promise at C,后续生成的无意义回调(console.log返回undefined)不会产生额外输出。
  3. 宏任务处理阶段

    • 微任务队列清空后,开始处理宏任务队列:
      • 第一个宏任务:执行sequenceB的setTimeout回调,输出🍅 Timeout at B。
      • 第二个宏任务:执行sequenceC的setTimeout回调,输出🍅 Timeout at C。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 03:12:45