JavaScript事件循环每轮只执行一个宏任务,随后清空全部微任务。宏任务如script、setTimeout、DOM事件等驱动循环节奏;微任务如Promise回调、queueMicrotask等在宏任务后立即批量执行,期间不插入宏任务或渲染。
JavaScript 的事件循环靠宏任务和微任务协同工作,不是“先宏后微”那么简单,而是“每轮只取一个宏任务,但紧跟着清空全部微任务”。理解这点,才能准确预判异步代码的执行顺序。
宏任务定义了事件循环的基本节奏。每次循环只执行一个宏任务,比如:
它像一拍一拍的鼓点,推动事件循环向前走。没有宏任务,事件循环就停摆。
微任务不开启新循环,只在当前宏任务执行完、下一个宏任务开始前集中执行。常见类型有:
关键规则:只要微任务队列非空,就会持续执行直到清空,期间不会穿插任何宏任务或渲染。
不是“宏→微→宏→微”,而是严格按以下四步循环:
例如:setTimeout(() => console.log(1)) 和 Promise.resolve().then(() => console.log(2)) 同时存在时,2 总是比 1 先输出——因为 setTimeout 是下一轮宏任务,而 Promise.then 是本轮宏任务结束后的微任务。
它直接影响代码可预测性和性能表现:
eMicrotask 或递归 resolve Promise,会阻塞渲染和后续宏任务,导致页面卡顿事件循环机制本身不复杂,但微任务的“清空式执行”容易被忽略,正是它让 JavaScript 在单线程下兼顾响应性与一致性。