javascript异步任务执行严格按微任务优先于宏任务的规则调度:每次宏任务执行后清空全部微任务,再取下一个宏任务;微任务队列一次性执行完毕,不中断、不穿插宏任务。

JavaScript 异步任务队列的执行不是“谁先注册谁先执行”,而是严格按两类队列的层级和清空规则来调度:微任务优先于宏任务,且每次只取一个宏任务,但会清空全部当前微任务。
微任务队列必须被完全清空
只要主线程空闲(即调用栈为空),引擎就会立即检查微任务队列,并**一次性执行其中所有已排队的微任务**,直到队列变空。这个过程不中断、不穿插宏任务。
- 常见微任务包括:Promise.then/catch/finally、async/await 后续代码、MutationObserver 回调、queueMicrotask()
- 哪怕在某个微任务里又创建了新的微任务(比如嵌套 Promise.then),它也会被加进当前轮次的微任务队列,并在本轮内执行完
- 微任务没有“下一个”概念——它是一次性全执行,不存在“只执行一个然后暂停”
宏任务每次只取一个,且必须等微任务清空后才开始
宏任务是事件循环的“主节奏单位”。每轮循环只从宏任务队列中取出最先进入的那个执行,执行完毕后,**立刻回到微任务队列检查并清空**,再取下一个宏任务。
- 常见宏任务包括:setTimeout/setInterval 回调、script 标签整体执行、I/O 操作完成回调、UI 渲染(浏览器)、DOM 事件处理函数
- 即使多个 setTimeout 都设为 0ms,它们仍按注册顺序排队,但必须等前一个宏任务执行完 + 微任务清空后,才轮到下一个
- 宏任务之间天然隔开,中间必有一次完整的微任务清空过程
执行顺序固定为:同步 → 微任务 → 宏任务 →(重复:微任务 → 宏任务)
整个流程由事件循环驱动,起点是同步代码执行完毕。之后不再依赖“谁快谁先”,而取决于任务类型归属和队列状态。
- 全局脚本本身是一个宏任务(常称“初始宏任务”),它的同步部分执行完,就触发第一轮微任务检查
- 每个宏任务执行时,可能产生新的微任务或宏任务,新微任务加入本轮微任务队列末尾,新宏任务则排到宏任务队列尾部
- 渲染(如浏览器中的 UI update)通常发生在宏任务执行完、微任务清空之后,属于宏任务间隙的可选步骤
Node.js 中 process.nextTick 是特例
在 Node 环境下,process.nextTick 的优先级高于普通微任务(如 Promise.then),它会在当前操作结束后、任何微任务之前立即执行。
- 这意味着:同步代码 → process.nextTick → Promise.then → setTimeout
- 但它仍是微任务层级内的细分,不改变“微任务先于宏任务”的大原则
- 浏览器环境没有 process.nextTick,所以该行为仅限 Node
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











