宏任务和微任务

作者:ZH彪
链接:https://www.jianshu.com/p/bcbf7894027c
来源:简书

微任务和宏任务皆为异步任务,它们都属于一个队列,主要区别在于他们的执行顺序,Event Loop的走向和取值。

宏任务和微任务的分配

宏任务                    浏览器          Node
I/O                       ✅            ✅
setTimeout                ✅            ✅
setInterval               ✅            ✅
setImmediate              ❌            ✅
requestAnimationFrame     ✅            ✅ 

         微任务
process.nextTick          ❌            ✅
MutationObserver          ✅            ❌
Promise.then catch finally✅            ✅

 

宏任务与微任务之间的执行顺序(同步任务->微任务->宏任务)
下面说说执行到宏任务后是怎么继续运行的
(这里声明下,整段js代码就是第一个大的宏任务,事件循环是由这第一个宏任务开始的,然后分出微任务,这里是为了理解微任务宏任务的执行区别就先跳过这第一层)

说一个很有名的银行例子:银行柜台前排着一条队伍,都是存钱的人,存钱属于宏任务,这条队伍就是宏任务队列,当一个‘宏大爷’被叫到了自己的号码,就上前去--被处理,处理存钱业务时,‘宏大爷’突然想给自己的存款办个微理财(微任务),那么银行职员就将他的需求添加到自己的微任务队列,大爷就不用再排队了,直接在存钱宏任务进行完后就处理衍生出来的微任务理财,办理财时大爷又说办个信用卡,那就又排到微任务队列里。但要是在此次存钱时‘宏大爷’说他还要存钱,且是他老伴要存钱,也是宏任务,但不好意思,需要取号到宏任务队列的后面排队(这里就是在宏任务进行时产生微任务和宏任务的处理方式)。

 

//宏任务1
    setTimeout(function () {
      console.log('1');//宏任务1
    });

    //Promise
    new Promise(function (resolve) {
      console.log('2');//同步任务1
      resolve();
    }).then(function () {
      console.log('3');//微任务1
    });

    //同步任务
    console.log('4');//同步任务2
    // 一步一步来分析,js可以看成是一个大的宏任务,以上是开始的一段,可以看到按照代码顺序有setTimeout、Promise、Promise.then()、console.log
    // setTimeout 是宏任务 、Promise是微任务、console.log是同步任务,而Promise是将异步的操作用同步的流程表达出来,所以在Promise里面的是同步任务、.then()里面的是微任务
    // 所以按照代码书写顺序和执行顺序 同步任务 > 微任务 > 宏任务,最先执行的是同步任务1,然后是同步任务2、微任务1、宏任务1
    //所以到目前为止打印出来的依次是:2 4 3 1

    //下面是宏任务2和宏任务3,注意宏任务2里面有很多同步任务和微任务,这些都是包括在宏任务2里面的
    //宏任务2
    setTimeout(function () {
      console.log('5');//宏任务2中的同步任务
      new Promise(function (resolve) {
        console.log('6');//宏任务2中的同步任务
        new Promise(function (resolve) {//宏任务2中的微任务
            console.log('x1');
            resolve();
          }).then(function () {
            console.log('X2');
          });
        setTimeout(function () {//宏任务2中的宏任务
          console.log('X3');
          new Promise(function (resolve) {//宏任务2中的宏任务中的同步任务
            console.log('X4');
            resolve();
          }).then(function () {//宏任务2中的宏任务中的微任务
            console.log('X5');
          });
        })
        resolve();
      }).then(function () {//宏任务2中的微任务
        console.log('7');
      });
    })
    //现在代码走到了宏任务2里面,开始按照顺序执行,首先可以看到宏任务2里面有两块,1个是宏任务2中的同步任务(console.log('6');),1个是 Promise
    // console.log('5'); 是同步任务,所以最先打印
    //宏任务2的第一个Promise里面包含的有:同步任务console.log('6')和Promise、微任务Promise.then、宏任务setTimeout
    //同步任务 '6'最先打印,然后是Promise里面的同步任务'x1',微任务Promise.then()里面的'x2'
    //而setTimeout是宏任务,得丢到宏任务列表的最后面去排队(目前的代码最后面排着的是宏任务3,所以这个宏任务得排在宏任务3的后面)
    //最后执行外面的微任务Promise.then() console.log('7');
    //所以这一块的打印顺序为:5 6 x1 x2 7

    //宏任务3
    setTimeout(function () {
      console.log('8');
    });
    // 因为宏任务3里面只有一个同步任务 所以直接输出 8 
    // 接下来执行宏任务2里面的宏任务 也就是刚被丢出来排在最后面的setTimeout,跟宏任务2的执行顺序同理,所以输出顺序为:x3 x4 x5
    //(对于这段代码node环境和浏览器环境输出一致)
    //最终输出答案:2,4,3,1,5,6,x1,x2,7,8,x3,x4,x5

无注解的原代码

setTimeout(function () {//宏任务1
      console.log('1');
    });
    new Promise(function (resolve) {
      console.log('2');//同步任务1
      resolve();
    }).then(function () {//微任务1
      console.log('3');
    });
    console.log('4');//同步任务2
    setTimeout(function () {//宏任务2
      console.log('5');//宏任务2中的同步任务
      new Promise(function (resolve) {
        console.log('6');//宏任务2中的同步任务
        new Promise(function (resolve) {//宏任务2中的微任务
            console.log('x1');
            resolve();
          }).then(function () {
            console.log('X2');
          });
        setTimeout(function () {//宏任务2中的宏任务
          console.log('X3');
          new Promise(function (resolve) {//宏任务2中的宏任务中的同步任务
            console.log('X4');
            resolve();
          }).then(function () {//宏任务2中的宏任务中的微任务
            console.log('X5');
          });
        })
        resolve();
      }).then(function () {//宏任务2中的微任务
        console.log('7');
      });
    })
    setTimeout(function () {//宏任务3
      console.log('8');
    });
    //(对于这段代码node环境和浏览器环境输出一致)
    //输出答案:2,4,3,1,5,6,x1,x2,7,8,x3,x4,x5

 

 

 
posted on 2022-08-18 16:45  会喷火的大魔王  阅读(132)  评论(0编辑  收藏  举报