一道带finally的宏任务微任务执行顺序的问题

374 阅读2分钟

背景

以前经常看见的题都是then链加setTimeout加setInterval等这些常见的宏任务微任务顺序题目,最近遇到加finally问题,着实有点迷,总结一下

题目

  console.log(1)

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

  Promise.resolve(3).then(res => {
    console.log(res);
  }).then(res => {
    Promise.resolve(4)
  }).finally(function(res) {
    console.log(res);
  }).then(res => console.log(res))

  Promise.resolve(5).then(res => {
    console.log(res)
  })
  
  /*
最终的结果为:
1
3
5
undefined
undefined
2

*/

解释

  1. 首先,同步执行代码,打印1
  2. 遇见setTimeout宏任务,添加宏任务队列,宏任务队列[2]
  3. 静态方法直接决议,把3添加到微任务队列中,
  4. 因为第一个then还在微任务队列中还没执行,所有后面的链式调用都没能执行
  5. 继续执行第二个直接决议5,添加到微任务队列中,微任务队列中有[3, 5]
  6. 没有同步代码,执行微任务3.打印3,then没有显式返回,所以返回了默认的用Promise.resolve()包装的undefined,并把then加入到微任务队列中
  7. 继续执行微任务中的代码,打印5,
  8. 继续执行微任务队列中Promise.resolve(4)这一块代码,这句代码就是直接决议了一个期约,没有什么用,也不作为返回值,所以还是默认返回了Promise.resolve()包装undefined的期约实例,把finally执行程序添加到为任务队列
  9. 继续执行微任务队列中finally的执行程序,打印了undefined,因为finally没有显式返回期约,所以直接原样返回父期约,即undefined,添加then处理程序到微任务队列
  10. 执行then处理程序,打印undefined
  11. 微任务处理完毕,检查宏任务队列,打印2

如果解释有什么问题,希望各路神仙指正