阅读 209

JS事件循环机制-宏任务和微任务

JavaScript 语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。所以所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。

消息队列:消息队列是一个先进先出的队列,它里面存放着各种消息。

事件循环:事件循环是指主线程重复从消息队列中取消息、执行的过程。

JS 中分为两种任务类型: 宏任务和微任务

在挂起任务时,JS 引擎会将所有任务按照类别分到这两个队列中,首先在宏任务的队列中取出第一个任务,执行完毕后取出微任务队列中的所有任务顺序执行;之后再取宏任务队列的任务,周而复始,直至两个队列的任务都取完。 宏任务和微任务的执行过程如下:

image.png

宏任务一般是:script,setTimeout,setInterval、setImmediate ; 微任务:原生Promise 

例子:

console.log(1)

setTimeout(() => {
    console.log(2)
}, 0)

new Promise(resolve => {
    console.log(3)
    setTimeout(() => {
        console.log(4)
        resolve()
    }, 0)
}).then(() => {
    console.log(5)
})

console.log(6)

复制代码

宏任务:2 4
微任务:5

  • 先遇到 console 直接 打印 1
  • 遇到 setTimeout 将 2 放到宏任务队列
  • 再向下执行遇到promise , 直接执行打印 3 , 再遇到 setTimeout 将 4 放到宏任务队列,遇到 then 将 5 放到微任务队列
  • 遇到 console 直接打印 6
  • 第一轮执行结束, 应该执行微任务队列打印 5 , 但是 then 是 promise resolve() 的语法糖, 只有执行了 resolve(), 才能执行打印 5
  • 因为没有其他的微任务,所以去执行宏任务队列,依次打印 2 4 , 再执行 resolve() 打印 5

执行结果: 1 3 6 2 4 5

练习题

async function async1() {
    console.log('async1 start');
    await async2();
    console.log('async1 end');
}

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

console.log('script start');

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

async1();

new Promise(function(resolve) {
    console.log('promise3');
    resolve();
}).then(function() {
    console.log('promise4');
});

console.log('script end');
复制代码

执行结果: script start --》async1 start --》promise1 --》 promise3 --》 script end --》 promise2 --》async1 end --》 promise4 --》 setTimeout

宏任务:setTimeout
微任务:promise2 , async1 end , promise4

文章分类
前端
文章标签