JavaScript,事件循环,微任务(Microtasks)和宏任务(Macrotasks)

August 29, 2023 作者: yijianhao 分类: 前端 浏览: 88 评论: 0

JavaScript,事件循环,微任务(Microtasks)和宏任务(Macrotasks)

事件循环

事件循环概念非常简单:有一个无限循环,JavaScript引擎等待任务,执行它们,然后休眠,然后等待更多任务

宏任务与微任务

微任务是指在当前的JavaScript代码之后,下一个宏任务之前执行的小而快的任务。微任务通常由promise或async/await创建。
宏任务是指在微任务队列为空之后执行的较大和独立的任务。宏任务通常由事件,定时器或I/O操作创建 。

例子:

console.log('start'); // macrotask

setTimeout(() => {
  console.log('timeout'); // macrotask
}, 0);

Promise.resolve().then(() => {
  console.log('promise'); // microtask
});

console.log('end'); // macrotask

输出结果为:

start
end
promise
timeout

执行顺序

它们的执行顺序是这样的:

  1. JavaScript引擎从宏任务队列中取出一个宏任务,比如console.log('start'),并执行它。
  2. 如果执行过程中产生了微任务,比如Promise.resolve().then(),就把它加入到微任务队列中。
  3. 如果执行过程中产生了宏任务,比如setTimeout(),就把它加入到宏任务队列中。
  4. 当当前的宏任务执行完毕后,JavaScript引擎会检查微任务队列,如果不为空,就依次取出并执行所有的微任务,直到清空为止。
  5. 当微任务队列清空后,JavaScript引擎会检查宏任务队列,如果不为空,就重复步骤1。

他们的规律是:每个宏任务之前,都要执行完所有的微任务。这样可以保证微任务能够及时地响应和更新应用的状态。

有些时候,执行的顺序在不同浏览器中会有差异,可以看一下我在知乎的上回答:

为什么这段代码在Chrome环境中不符合事件循环机制? https://www.zhihu.com/question/619560968/answer/3187177238

宏微判断方法

判断任务是宏任务还是微任务的方法是:

  • 如果任务是由事件,定时器,或I/O操作创建的,那么它是一个宏任务。
  • 如果任务是由promise或async/await创建的,那么它是一个微任务。
  • 如果任务是由微任务创建的,那么它也是一个微任务。
  • 如果任务是由宏任务创建的,那么它也是一个宏任务。

参考

  1. Event loop: microtasks and macrotasks - The Modern JavaScript Tutorial.
  2. javascript - Macro task vs micro task - Stack Overflow.
  3. Microtask and Macrotask: A Hands-on Approach - Medium.

评论