JavaScript事件循环中,宏任务执行完后立即清空所有微任务队列,再取下一个宏任务;宏任务包括script、setTimeout等,微任务包括Promise.then、queueMicrotask等。

JavaScript 的事件循环机制决定了宏任务和微任务的执行顺序:每次宏任务执行完后,会清空当前所有微任务队列,再取下一个宏任务。掌握这个规律,就能准确预测异步代码的执行时序。
宏任务与微任务的典型代表
理解哪些是宏任务、哪些是微任务,是分析执行顺序的基础:
-
宏任务:script 脚本整体、
setTimeout、setInterval、setImmediate(Node.js)、I/O、UI 渲染等 -
微任务:
Promise.then/catch/finally、queueMicrotask()、MutationObserver、process.nextTick(Node.js)
事件循环的执行流程
浏览器或 Node.js 运行时每次循环遵循固定步骤:
- 从宏任务队列中取出一个任务(如 setTimeout 回调)并执行
- 执行过程中遇到微任务(如 new Promise().then),将其加入当前微任务队列
- 宏任务执行完毕后,立即执行所有已排队的微任务(按先进先出顺序),直到微任务队列为空
- 渲染(浏览器环境,若需要)
- 开始下一轮循环,取下一个宏任务
用经典例子验证交替规律
看这段代码的输出顺序:
立即学习“Java免费学习笔记(深入)”;
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
console.log(1); setTimeout(() => console.log(2), 0); Promise.resolve().then(() => console.log(3)); console.log(4);
执行过程如下:
- 同步代码执行:打印 1 → 4
- 遇到
setTimeout:注册为宏任务(进入宏任务队列) - 遇到
Promise.then:注册为微任务(进入微任务队列) - 同步脚本结束,检查微任务队列 → 执行 3
- 微任务清空,开始下一轮事件循环 → 取出宏任务 → 执行 2
最终输出:1 → 4 → 3 → 2
嵌套异步场景下的关键细节
微任务可以触发新的微任务,它们会在本轮继续执行,不会等到下一轮:
-
Promise.resolve().then(() => { Promise.resolve().then(() => console.log('nested')) })中的嵌套then仍属于本轮微任务,会紧接在外部then后执行 - 但
setTimeout内再调用setTimeout,生成的是新宏任务,要排到后续轮次 -
queueMicrotask和Promise.then在同一微任务队列中,按注册顺序执行,不区分来源
不复杂但容易忽略:微任务不是“比宏任务快一点”,而是“必须在当前宏任务结束后、下一个宏任务开始前全部执行完”。抓住这个核心,就能稳稳推演任意组合的异步行为。

















