事件循环规定每个宏任务执行完后必须立刻一次性清空所有微任务,微任务是依附于当前宏任务的收尾环节,按入队顺序执行且新产生的微任务会追加至当前队列尾部直至为空,之后才取下一个宏任务。

因为事件循环规定:每个宏任务执行完后,必须立刻、一次性清空所有已排队的微任务,之后才允许取下一个宏任务。
微任务被设计为“当前宏任务的收尾环节”
JavaScript 引擎把微任务定位在宏任务结束、下一轮开始之间的“间隙”。它不是独立调度单元,而是依附于当前宏任务的补充执行阶段。比如 Promise.then 回调,语义上就是“等这个操作完成之后马上做点什么”,而不是“等一会儿再做”。这种语义直接映射到执行机制上——必须紧接在当前同步逻辑之后、且不被其他宏任务打断。
事件循环每次只推进一个宏任务,但会跑完全部微任务
- 宏任务队列是 FIFO,但每次只取一个(如 setTimeout 回调、click 事件、整个 script 标签)
- 一旦这个宏任务的同步部分执行完毕,引擎立刻转向微任务队列
- 微任务队列按入队顺序逐个执行,过程中新产生的微任务(比如在 then 里再链一个 then)也会加入当前队列尾部,继续执行,直到彻底为空
- 只有这时,事件循环才回到宏任务队列,取下一个
这是引擎层面的硬性规则,不是优先级投票
不是“微任务优先级高所以抢着执行”,而是规范强制要求:宏任务和微任务之间存在确定的嵌套关系。你可以理解为——每一个宏任务都自带一个微任务清空环节,就像函数执行完自动执行 finally 块一样,不可跳过、不可延迟。
实际效果就是“隔离”与“即时响应”
这种机制保证了两件事:
立即学习“Java免费学习笔记(深入)”;
- 上一个宏任务产生的微任务,绝不会拖到下一个宏任务之后;哪怕 setTimeout(0),它的回调也一定排在所有当前微任务之后
- 异步逻辑(如 Promise 链、await 后续)能快速收敛,避免被 UI 渲染、定时器等宏任务插队打断,提升响应一致性


















