谈谈异步任务中的宏任务和微任务

79 阅读1分钟

假如你拿到这道面试题,让你写出执行结果,你给出的答案是什么?

    setTimeout(function () {
      console.log('1');
    })
    new Promise(function (resolve) {
      console.log('2');
      setTimeout(function () {
        console.log('3');
      })
      resolve(true)
    }).then(function () {
      console.log('4');
    })
    console.log('5')

话不多说:从简单的例子来看

    console.log(1);
    setTimeout(()=>{
      console.log(2);
    })
    Promise.resolve().then(()=>{
      console.log(3);
    })
    console.log(4);
    // 答案:1 4 3 2

先知道宏任务和微任务:

微任务宏任务
Promise.then()、Promise.catch()、Promise.finally()、async...await、process.nextTick(Node.js 环境)Dom事件、ajax请求 、setTimeout、setInterval 、setImmediate(Node.js 环境)

根据打印结果,可以发现微任务比宏任务执行的时间早,有没有想过为什么?其实dom执行前发生的是微任务,而dom执行后发生的是宏任务。执行时间:微任务 > DOM渲染 > 宏任务

那么文章最开始的段代码的执行结果究竟是怎么样的呢?先打印2,因为Promise本身是同步任务;再打印5;然后再打印4,因为Promise是微任务;再执行队列里面的宏任务1和3;所以执行结果是:2 5 4 1 3

    console.log(1);
    new Promise(function (resolve) {
      console.log('2');
      setTimeout(function () {
        console.log('3');
      })
      resolve(true)
    }).then(()=>{
      console.log(4);
    }).catch(()=>{
      console.log(5);
    }).finally(()=>{
      console.log(6);
    })
    // 1 2 4 6 3
    console.log(1);
    new Promise(function (resolve) {
      throw new Error(123)
      resolve(true)
    }).then(()=>{
      console.log(4);
    }).catch(()=>{
      console.log(5);
    }).finally(()=>{
      console.log(6);
    })
    // 1 5 6 

Tips then和catch的执行需要看Promise是否执行有误,没错误执行then(),反之执行catch(),且finally()的打印结果一定在then和catch之后。把then、catch、finally当成一个整体就好了,只是有先后而已。