微任务机制是javascript事件循环中优先级最高的异步调度方式,其回调在当前同步任务结束后、下一个宏任务开始前立即执行;典型触发方式包括promise链、queuemicrotask()、mutationobserver及async函数隐式promise;它比settimeout(0)更快,因微任务在宏任务前执行,且适用于“下一帧前”轻量调度,但需避免堆积导致性能问题。

微任务的典型触发方式
只有特定操作会把回调推入微任务队列,不是所有异步都自动走微任务:
- Promises 的 .then()/.catch()/.finally():只要 Promise 状态变为 fulfilled 或 rejected,其回调就进入微任务队列
- queueMicrotask():原生 API,专为手动调度微任务设计,语义清晰、兼容性好(现代浏览器 & Node.js 12+)
- MutationObserver 的回调:DOM 变更监听器的回调也属于微任务,适合需要响应 DOM 更新但又不想用 setTimeout 的场景
- async 函数隐式返回的 Promise:哪怕函数体里没 await,return 值也会被 Promise.resolve() 包装,.then() 就是微任务
为什么微任务比 setTimeout(0) 更快?
两者看似都是“立刻执行”,但执行时机有本质区别:
- setTimeout(0) 放入宏任务队列,必须等当前执行栈清空 + 所有微任务执行完 + 渲染(如有)之后才轮到它
- Promise.then() 或 queueMicrotask() 放入微任务队列,只要同步代码一结束,立刻连续执行,中间不插任何其他任务
- 举例验证:
console.log('1'); setTimeout(() => console.log('2'), 0); Promise.resolve().then(() => console.log('3')); console.log('4');输出顺序一定是 1 → 4 → 3 → 2,说明微任务在宏任务之前执行
实用技巧:用微任务做“下一帧前”的轻量调度
当你要确保某段逻辑在当前同步流程结束后、浏览器渲染前执行(比如批量更新状态后统一响应),微任务是理想选择:
- 避免使用 setTimeout(0) 做“防抖式”延迟,改用 queueMicrotask() 更精准、无额外计时开销
- 在 Vue/React 等框架中,$nextTick 或 flushSync 底层依赖的就是微任务机制
- 手动实现“批处理”:收集多个变更,用一次 queueMicrotask() 统一提交,减少重复计算或 DOM 操作
- 注意:不要在微任务里递归调用 queueMicrotask(),否则会阻塞主线程,导致页面卡死
常见误区提醒
微任务不是万能加速器,用错反而影响性能:
- 大量 Promise 链或嵌套 queueMicrotask() 会造成微任务队列堆积,延迟后续宏任务(如用户点击、动画帧)
- 微任务无法替代 requestAnimationFrame:需要与屏幕刷新同步的操作(如动画),仍需 rAF
- await 后面的代码不是“微任务”,而是由 Promise 状态切换触发的微任务链,逻辑上等价于 .then()











