宏任务与微任务是嵌套协作而非并列关系:每个宏任务执行完后立即清空全部微任务,再取下一个宏任务;微任务由JS引擎自动触发,在当前宏任务结束且调用栈为空时立刻执行,且队列一次性清空、新微任务追加后继续执行。

宏任务和微任务不是并列排队、轮流执行的关系,而是嵌套协作的结构:每个宏任务执行完后,立刻清空整个微任务队列,再取下一个宏任务。这个“宏→微→宏→微”的节奏,才是事件循环的真实周期。
执行触发时机不同
宏任务由宿主环境(浏览器或 Node.js)调度,在每轮事件循环起始时从宏任务队列取出一个执行;微任务则由 JavaScript 引擎自动触发,只要当前宏任务结束、调用栈为空,就立即开始执行,不等待下一轮循环。
- 宏任务:setTimeout、setInterval、script 全局代码、I/O、UI 渲染、DOM 事件回调
- 微任务:Promise.then/catch/finally、queueMicrotask、MutationObserver 回调
队列清空方式差异明显
宏任务队列每次只取一个任务执行,执行完即暂停,等微任务全部跑完才继续;而微任务队列是“一次性清空”——只要队列非空,就持续取任务执行,期间新产生的微任务(比如在 then 里再链一个 then)会追加到当前队列末尾,继续执行,直到彻底为空。
- 宏任务:严格 FIFO,一次一任务,中间可插入 UI 渲染
- 微任务:递归式消费,无中断,执行期间不交出控制权
实际执行顺序可推导
同步代码 → 当前宏任务内产生的所有微任务 → 下一个宏任务 → 新一轮微任务……这个链条决定了真实输出顺序。例如:
console.log('1');setTimeout(() => console.log('2'), 0);
Promise.resolve().then(() => console.log('3'));
console.log('4');
输出一定是 1 → 4 → 3 → 2,因为 Promise.then 是微任务,在同步代码('1'、'4')之后、setTimeout(宏任务)之前执行。
优先级与响应敏感度关联
微任务优先级高,适合需要紧贴当前操作反馈的逻辑,比如 Promise 链式处理、状态更新后的视图同步;宏任务更适用于延后、解耦或需让出主线程的场景,如定时提醒、批量 DOM 更新、动画帧协调(requestAnimationFrame 属于宏任务,但会在渲染前执行)。
- 想立刻响应异步结果?用 Promise.then 或 queueMicrotask
- 想延迟执行且允许 UI 更新?选 setTimeout 或 requestAnimationFrame


















