JS中的宏任务和微任务|青训营笔记

122 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 10 天

在上一篇笔记中介绍了JS中的同步任务和异步任务,今天要介绍里面更重要的内容--宏任务和微任务。

一、同步任务和异步任务

1、同步任务:

同步任务是指在主线程上排队执行的任务,只有前一个任务执行完毕,才能继续执行下一个任务,当我们打开网站时,网站的渲染过程,比如元素的渲染,其实就是一个同步任务。

2、异步任务:

在JS的设计中有一个任务队列,这是不同于主线程的队列。在遇到异步任务时,会放置在任务队列中,等待同步任务执行完之后才会放入主线程当中。

二、宏任务和微任务

异步任务细分为宏任务和微任务。

1、宏任务

宏任务主要有以下几种:

  • 主代码块
  • setTimeout
  • setInterval
  • DOM事件
  • AJAX请求
  • IO
  • UI渲染

2、微任务

微任务主要有以下几种:

  • Promise.then finally catch
  • process.nextTick
  • async/await
  • MutationObserver

3、执行顺序

其实宏任务和微任务是这样的,在代码执行时,遇到微任务会放入微任务队列中。在每一次完成宏任务之后,都会将微任务队列中的任务清空。不过实际上微任务优先度应该是比宏任务高的,只不过在第一次执行时微任务队列中没任何微任务,所以会先执行主代码块并将里面的微任务提取出来,再去执行微任务。
下面是一个例子:

setTimeout(function() {
    console.log('setTimeout');
})
 
new Promise(function(resolve) {
    console.log('promise1');
}).then(function() {
    console.log('then1');
})

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

结合之前的同步与异步任务来看,代码的执行结果如下:

promise1
promise2
console
then1
then2
setTimeout

执行逻辑如下:

  1. 首先从上往下将主代码块作为宏任务执行
  2. 先遇到setTimeout事件,将其放入宏任务队列当中
  3. 然后进入第一个promise,先输出promise1(同步任务),然后将then1放入微任务队列中
  4. 在然后进入第二个promise,同理先输出promise2(同步任务),然后将then2放入微队列之中
  5. 遇到console,输出console(同步任务)
  6. 以上为第一个宏任务,然后寻找微任务执行,按照顺序先输出then1,再输出then2
  7. 微任务队列清空后,执行下一个宏任务,这里即为setTimeout事件,输出setTimeout
  8. 执行完毕

以上即为宏任务和微任务的例子和说明。