微任务队列在每个宏任务结束后立即被引擎强制、同步、耗尽式清空,执行完当前宏任务同步代码后立刻进入微任务处理,直至队列为空,期间新产生的微任务也加入本轮处理,且该过程阻塞UI渲染和下一宏任务。
微任务队列在每个宏任务执行完后,由 javascript 引擎自动、强制、同步地清空——不是靠手动干预,也不是定时检查,而是事件循环的硬性阶段规则。
清空发生在宏任务结束的精确时刻
只要当前宏任务的同步代码执行完毕(调用栈完全清空),引擎立刻进入微任务处理阶段,不等待、不跳转、不响应新事件。这个时机严格卡在:
- 宏任务函数返回之后
- UI 渲染之前
- 下一个宏任务被取出之前
清空是“耗尽式”循环,不是只执行一个
引擎用一个不可中断的 while 循环持续取出并执行微任务,直到队列为空。关键点在于:
- 每次只取队首任务执行,执行完再看队列是否还有任务
- 执行过程中产生的新微任务(比如
.then()里再创建 Promise 或调用queueMicrotask)会追加到队尾,继续被本轮循环处理 - 不会按“初始数量”执行固定轮次,而是以队列是否为空为唯一退出条件
清空范围仅限于当前宏任务产生的微任务
微任务队列不是全局累积池,而是按宏任务粒度隔离的:
- 上一个宏任务留下的微任务早已清空,不会延续到本轮
- 当前宏任务中产生的所有微任务(包括嵌套生成的)都归入本轮清空范围
- 即使
setTimeout(0)已就绪,也必须等本轮微任务全部跑完才能执行
浏览器渲染和宏任务调度都得等它结束
微任务清空是渲染管线和事件循环的“守门人”:
- UI 渲染(包括
requestAnimationFrame回调)只能在微任务队列彻底清空后触发 - 点击、滚动等新用户事件会被暂存为宏任务,排队等待下一轮,期间不打断当前微任务执行
- 若微任务持续追加(如无限递归调用
queueMicrotask),实际引擎会设保护阈值(如 V8 的约 1000 层)防止卡死,但规范本身要求“清空至空”

















