微任务执行优先级高于宏任务,因为事件循环要求每个宏任务执行完毕后必须清空全部微任务队列才取下一个宏任务;promise.then、queuemicrotask()、mutationobserver等微任务均在此阶段立即、连续执行,且早于渲染和下一宏任务。

微任务执行优先级比宏任务高,是因为事件循环的调度规则明确要求:每个宏任务执行完后,必须先清空整个微任务队列,才能去取下一个宏任务。
微任务总在宏任务“夹缝”中执行
JavaScript 引擎每完成一个宏任务(比如一段脚本、一次 setTimeout 回调),不会直接跳到下一个宏任务,而是立刻转向微任务队列。只要队列里有任务(哪怕刚被新加入),就全部执行完——这个过程不中断、不穿插宏任务。
- Promise.then/catch/finally 是典型的微任务,写在 setTimeout 回调里,也会等该回调执行完才运行,且一定早于下一个宏任务
- queueMicrotask() 显式插入的任务,同样遵循这一规则,哪怕它出现在宏任务快结束时,也 guaranteed 在下一宏任务前执行
- MutationObserver 的回调也是微任务,DOM 变更后不会立刻触发,而是排队等到当前宏任务收尾时统一处理
宏任务是“轮次单位”,微任务是“即时响应单元”
宏任务代表浏览器或运行时划分的一段相对独立的工作(如整体脚本、定时器回调、用户点击事件),每次只取一个;而微任务的设计目标就是快速响应、低延迟,比如 Promise 链需要保证状态流转及时、避免异步结果“卡顿”。这种职责差异决定了它们的调度层级不同。
- UI 渲染通常发生在微任务清空之后、下一个宏任务开始之前,所以微任务能赶在页面刷新前更新状态
- process.nextTick(Node.js)甚至比 Promise 微任务还靠前,但它属于 Node 特有机制,浏览器环境不适用
- requestAnimationFrame 虽然常用于动画,但归类为宏任务,因此它的回调一定排在当前所有微任务之后
实际影响:顺序不是“谁先注册谁先跑”
任务入队时间不影响执行顺序,关键看类型和所处宏任务上下文。比如 setTimeout(fn, 0) 注册得再早,只要它是宏任务,就一定排在当前宏任务里的所有微任务之后。
- 同步代码 → 当前宏任务内微任务 → 渲染(浏览器)→ 下一个宏任务
- 一个宏任务里产生的新微任务(比如在 Promise.then 里又调用 Promise.resolve().then),会加入当前微任务队列末尾,并在本轮清空阶段一并执行
- 多个 setTimeout 创建的宏任务,按注册顺序排队,但每个都必须等前一个宏任务 + 其全部微任务走完才能轮到
这种设计让微任务天然具备“插队权”,不是靠抢占资源,而是靠事件循环的硬性流程保障。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











