我们常说的微任务和宏任务是怎么回事? 200字讲明白

118 阅读2分钟

在 JavaScript 中,任务分为微任务(microtask)和宏任务(macrotask),它们用于管理代码的执行顺序和优先级。

宏任务是由浏览器 API 提供的异步任务,例如 setTimeout、setInterval、XHR 请求等。宏任务会被添加到任务队列中,在主线程执行栈中的所有任务执行完毕后立即执行。

而微任务是在当前任务执行结束后,紧接着执行的任务。微任务通常是由 Promise 的处理程序、MutationObserver 或者 process.nextTick 等触发的。

下面是它们的执行顺序:

  1. 首先,JS 运行时会执行同步任务,也就是主线程中的代码,直到执行栈为空。

  2. 当执行栈为空时,JS 引擎会检查微任务队列。如果微任务队列中有任务,就按照先进先出的顺序依次执行所有微任务,直到微任务队列为空。

  3. 当微任务队列为空时,JS 引擎会检查宏任务队列。

  4. 如果宏任务队列中有任务,则从队列中选择一个最早进入的任务执行。执行完该任务后,返回步骤 2,检查微任务队列。

  5. 当所有微任务和宏任务都执行完毕时,JS 运行时会再次检查是否有新的微任务加入,如果有,则重复步骤 2;如果没有,则等待新的宏任务加入。

需要注意的是,每个宏任务执行完毕后,浏览器会检查页面是否需要进行渲染(重绘和重排)。如果需要渲染,则将进行渲染操作,然后再执行下一个宏任务。

在实际应用中,了解微任务和宏任务的执行顺序对于编写高效的异步代码至关重要。例如,如果你希望在当前宏任务执行结束后立即执行某些代码,可以使用 Promise 的 then、catch 或者 finally 方法来创建微任务。

示例:

console.log('主线程开始');

setTimeout(() => {
  console.log('宏任务1');
}, 0);

Promise.resolve().then(() => {
  console.log('微任务1');
}).then(() => {
  console.log('微任务2');
});

console.log('主线程结束');

输出:

主线程开始
主线程结束
微任务1
微任务2
宏任务1

根据上述示例,我们可以看到微任务总是在当前宏任务执行结束前执行,而且微任务的执行顺序是按照添加的顺序执行的。

通过理解微任务和宏任务的执行机制,你可以更好地控制代码的执行顺序,以满足特定的业务需求。