执行顺序为同步→微任务→宏任务:同步代码立即执行,微任务在本轮末尾集中执行,宏任务排队至下一轮。

肉眼走读执行顺序,关键不是背规则,而是把代码拆成三类“时间片”:同步代码、微任务、宏任务。只要标清楚每行属于哪一类,再按“同步 → 微任务 → 宏任务”顺序串起来,输出结果就一目了然。
第一步:识别三类代码块
不用记术语,只看行为特征:
-
同步代码:立刻打印、立刻计算、立刻调用。比如
console.log(1)、new Promise((resolve) => { console.log(2); resolve(); })里的console.log(2)和resolve()都算同步。 -
微任务:带
.then()、.catch()、.finally()的回调;还有queueMicrotask()。它们不马上执行,但会“插队”在本轮末尾集中跑完。 -
宏任务:
setTimeout、setInterval的回调;整个<script></script>标签本身也算一个初始宏任务。
第二步:逐行标注并排序
拿这段典型代码为例:
console.log('A'); // 同步
Promise.resolve().then(() => console.log('B')); // 微任务
setTimeout(() => console.log('C'), 0); // 宏任务
console.log('D'); // 同步
标注后变成:
- 同步:A → D
- 微任务:B
- 宏任务:C
按顺序连起来就是:A → D → B → C。
第三步:注意构造函数和 then 的分工
很多人卡在 new Promise 里写了 console.log 却搞不清为啥它比 .then 先输出——因为:
- 构造函数里的所有代码(包括
resolve()前的console.log)都是同步执行; -
.then()回调只在 Promise 状态变为 fulfilled 后才进微任务队列,哪怕resolve()是同步调的,.then也得等同步代码跑完再执行。
所以 new Promise(() => console.log('X')).then(() => console.log('Y')) 必定先输出 X,再输出 Y。
第四步:多个定时器和多个 then 的排队逻辑
它们各自内部守 FIFO(先到先服务),但两类之间不混排:
- 多个
.then()按注册顺序进微任务队列,前一个执行完,下一个立刻排队(哪怕它返回新 Promise,也要等那个 Promise settle 后再入队); - 多个
setTimeout(..., 0)按调用顺序进宏任务队列,谁先写谁先排前面; - 但所有微任务一定在所有宏任务之前执行——哪怕你写了十个
setTimeout(..., 0),只要有一个.then(),它就一定比这十个都早。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











