js的微任务和宏任务

66 阅读2分钟

在js中,任务分为微任务(microtask)和宏任务(macrotask)是事件循环(event loop)的一部分,用于处理异步代码的执行。

宏任务(Macrotasks)

宏任务是指执行栈中按照顺序等待执行的任务。宏任务队列是先进先出的,即排在队列前面的宏任务会优先执行。常见的宏任务包括:

  • script(整体代码)
  • setTimeout
  • setInterval
  • setImmediate(Node.js环境)
  • I/O 操作
  • UI 渲染(浏览器环境)

微任务(Microtasks)

微任务通常在宏任务执行完毕后立即执行,微任务队列是后进先出的,也就是说微任务队列中的任务会按照“后进先出”的顺序执行。这样设计是为了确保微任务尽快执行,而不需要等待其他宏任务。常见的微任务包括:

  • Promise 的回调(.then(), .catch(), .finally())
  • process.nextTick(Node.js环境)
  • Object.observe(已废弃)
  • MutationObserver(监听DOM变化)

执行顺序

在JavaScript的事件循环中,微任务和宏任务的执行顺序如下:

  1. 执行栈为空时,首先检查微任务队列是否为空。
  2. 如果微任务队列不为空,则执行微任务队列中的所有任务,直到微任务队列为空。
  3. 如果微任务队列为空,则执行宏任务队列中的一个任务。
  4. 执行完一个宏任务后,回到第1步。

这个循环过程就是事件循环,确保了JavaScript的非阻塞异步行为。

console.log('script start');

setTimeout(function() {
  console.log('setTimeout');
}, 0);

Promise.resolve().then(function() {
  console.log('promise1');
}).then(function() {
  console.log('promise2');
});

console.log('script end');

script start
script end
promise1
promise2
setTimeout

在这个例子中,script start 和 script end 首先打印,因为它们是同步代码。然后,JavaScript引擎会处理微任务队列中的Promise回调,打印promise1promise2。最后,执行宏任务队列中的setTimeout,打印setTimeout