JavaScript微任务是什么_它何时执行?

微任务是异步操作中优先级最高的任务,包括Promise回调、MutationObserver、queueMicrotask等,总在当前宏任务结束后、下一个宏任务开始前清空执行,易阻塞渲染且需防无限递归。

JavaScript微任务是异步操作中优先级最高的一类任务,它们会在当前同步代码执行完后、下一次事件循环开始前立即执行。

微任务有哪些常见类型

常见的微任务包括:

  • Promise.then() / .catch() / .finally() 中的回调函数
  • MutationObserver 的回调
  • queueMicrotask() 显式加入的函数
  • Promise 构造函数中 executor 内部的同步代码(注意:不是微任务本身,但会影响微任务队列)

微任务的执行时机很明确

它总是在以下两个节点之间执行:

  • 当前宏任务(如 script 脚本、setTimeout 回调、事件处理函数等)执行完毕后
  • 下一个宏任务从事件队列中取出并执行之前

而且,只要微任务队列不为空,就会持续清空——也就是说,新加入的微任务会紧接着前面的微任务执行,形成“微任务风暴”(比如在 Promise 回调里又创建新的 Promise)。

和宏任务对比更清楚

宏任务(如 setTimeout、setInterval、I/O、UI 渲染)每次只执行一个,执行完就检查微任务队列;而微任务队列会一次性清空。例如:

console.log(1);
setTimeout(() => console.log(2), 0);
Promise.resolve().then(() => console.log(3));
console.log(4);
// 输出顺序:1 → 4 → 3 → 2

这是因为 1 和 4 是同步代码,3 是微任务,2 是下一轮事件循环的宏任务。

实际开发中要注意什么

微任务虽然快,但滥用可能导致:

  • 阻塞 UI 渲染(因为微任务执行期间不会触发渲染)
  • 递归调用 queueMicrotask 或链式 Promise 不加限制,引发栈溢出或界面卡死
  • 与 setTimeout(0) 的行为差异被误用(后者是宏任务,有最小延迟且可被节流)

需要精细控制异步节奏时,优先想清楚该用微任务还是宏任务。

基本上就这些。