promise JS宏任务微任务的执行顺序

来源:segmentfault.com 更新时间:2023-05-25 21:55

题目描述:JS宏任务微任务的执行顺序为什么是这样的


console.log(1);

setTimeout(() => {
  console.log(2);
  Promise.resolve().then(() => {
    console.log(3)
  });
});

new Promise((resolve, reject) => {
  console.log(4)
  resolve(5)
}).then((data) => {
  console.log(data);
  
  Promise.resolve().then(() => {
    console.log(6)
  }).then(() => {
    console.log(7)
    
    setTimeout(() => {
      console.log(8)
    }, 0);
  });
})

setTimeout(() => {
  console.log(9);
})

console.log(10);

结果: 1 4 10 5 6 7 2 3 9 8

建议先简单了解下JS异步代码的运行原理,包括:

  • 进程与线程
  • JavaScirpt是单线程的
  • 执行栈
  • 浏览器中的 Event Loop

常见的宏任务有:

  • script
  • 定时器:setTimeout,setInterval,setImmediate
  • I/O
  • UI渲染

常见的微任务有:

  • Promise
  • MutationObserver
  • Node中的process.nextTick

回到上述代码,执行顺序如下:

  1. 首先执行同步代码,同步代码包括 console.log,Promise的创建也属于同步代码,打印 1 4 10
  2. 所有的同步代码执行完后,执行栈为空,查询是否有异步代码需要执行
  3. 首先会执行微任务,进入Promise,执行resolve,在第一个then回调中打印出 5
  4. 继续执行微任务,进入两个then回调,打印 6,7
  5. then回调中的setTimeout属于宏任务,会被放到task队列,此时的task队列中有三个宏任务
  6. 所有微任务执行完成后开始执行宏任务,第一个setTimeout打印 2,接下来又遇到微任务,转而执行微任务,打印 3
  7. 接下来执行剩下的两个宏任务,依次打印 9,8