首页 > 其他分享 >宏任务和微任务

宏任务和微任务

时间:2022-08-18 16:56:17浏览次数:42  
标签:function resolve console log 任务 Promise

作者: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

 

 

 

标签:function,resolve,console,log,任务,Promise
From: https://www.cnblogs.com/Luffy-RedRoc/p/16599280.html

相关文章

  • 完整实现-通过DelayQueue实现延时任务
    实现延时任务有很多的方法,网上关于延时任务的实现的文章已经不少了。比如:实现延时任务的10种方法等等。但是这些文章基本上都是将方法大概的列举一下,给出部分示例代码,对于......
  • C# Winform在任务管理器中隐藏指定窗口
    业务环境需求:每次打开主窗体都需要进行登录验证,关闭主窗体只是最小化到系统托盘,并不是真正的退出程序,现关闭主窗体后发现任务管理器中还能找到主窗体的任务,然后能从......
  • windows定时任务执行python爬虫
    有一些定时爬取的操作,适合用定时任务去执行。个人单独用的项目不适合放在工作所用的服务器上,也没必要单独买个服务器,我们windows电脑本身就有这项功能。接下来是一个wi......
  • javascript 执行机制(同步、异步、微任务、宏任务)
    一、关于javascriptJS是一门单线程语言,这意味着所有的任务都需要排队,前一个任务结束才会执行后一个任务如果前一个任务耗时很长,后一个任务就不得不一直等着。这样所导致的......
  • 在asp.net中开启后台任务
    开始后台任务一般是Task.Run()查在asp.net时进行可能会被回收,导致Task中断。在Asp,net中有专门的后台任务函数: System.Web.Hosting.HostingEnvironment.QueueBackgroun......
  • Vue+Koa+MongoDB从零打造一个任务管理系统
    大概是在18年的时候,当时还没有疫情。当时工作中同时负责多个项目,有PC端运营管理后台的,有移动端M站的,有微信小程序的,每天git分支切到头昏眼花,每个需求提测需要发送邮......
  • Jenkins 定时任务
    每次手动触发job构建,是很麻烦的一件事情,job中可以配置定时构建,今天就来分享下定时构建;构建分为两种:定时构建和轮询SCM。一.定时构建Jenkins采用了著名的UNIX任务调度工......
  • spring boot 定时任务使用
    1.在Springboot启动类上添加注解:@EnableScheduling2.在需要执行定时任务的类上加@Component注解,在需要执行的方法上加@Scheduled(cron="0/2*****")注解@Compon......
  • shell中系统任务设置
    shell中系统任务设置1、系统启动流程启动计算机的硬件(BIOS)读取时间选择对应的启动模式(USBHDDEFI)如果是Linux系统,回去找/boot目录.引导这个系统启动计算机系统......
  • 基于 dapr cron binding 实现定时任务
    这两天在开发中的一个功能需要用到定时任务,正好最近准备更多使用dapr,于是想到这个经常重复编写的代码看是否可以让dapr代劳,了解之后发现可以通过cronbinding实现,动手......