JS进阶 | 当事件循环遇到resolve()

76 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第8天,点击查看活动详情

宏任务和微任务是面试题中会高频出现的考点,主要的形式是根据代码写出程序运行后的输出结果。

在此之前,需要先掌握什么是异步编程,以及宏任务和微任务的执行顺序。

预备知识

1.异步任务

分为宏任务和微任务,当一个宏任务执行完毕,会进入任务队列将里面的微任务全部执行完, 再进入下一个宏任务。

以下几种是在面试题中经常会遇到的几类任务:

  1. 宏任务(macrotask)

    整体代码、setTimeOut、setInterval

  2. 微任务(microtask)

    Promise.then、Promise.catch、Promise.finally(Promise中的代码段属于同步任务)

2.promise中的resolve()

  • resolve()执行后,promise的状态会变为为fullfilled
  • promise的状态为fullfilled后,promise.then()才会被执行:
  • 如果没有执行resolve(),then里面的函数不会被推入微任务中

如下,这种属于立即执行的resolve(),它会在本轮事件循环完成前执行,并不会立即执行或者下一轮执行

Promise.resolve().then(function () {
  console.log('1');
});

resolve里的参数就是传入then的数据

Promise.resolve('foo')
等价于:
new Promise(resolve => resolve('foo'))

例1

console.log('start')
setTimeout(function() {
  console.log('A2')
}, 0)
Promise.resolve().then(function() {
  console.log('A3')
})
new Promise(function(resolve, reject) {
  console.log('A4')
  setTimeout(function() {
    console.log('A5')
    resolve('A6')
  }, 0)
}).then(res => {
  console.log('A7')
  setTimeout(function() {
    console.log(res)
  }, 0)
})

运行结果:

  • start
  • A4
  • ------ (第一轮宏任务结束) ------- 微任务队列:无 ----- 宏任务队列:A2、A5 ------
  • A2
  • ------ (第二轮宏任务结束) ------- 微任务队列:A3 ----- 宏任务队列:A5 ------
  • A3
  • ------ (清空微任务队列结束) ------- 微任务队列:无 ----- 宏任务队列:A5 ------
  • A5
  • ------ (第三轮宏任务结束) ------- 微任务队列:A7 ----- 宏任务队列:res (即A6) ------
  • A7
  • ------ (清空微任务队列结束) ------- 微任务队列:无 ----- 宏任务队列:A6 ------
  • A6
  • ------ (第四轮宏任务结束) ------- 微任务队列:无 ----- 宏任务队列:无 ------

例2

const Fn = function() {
  new Promise((resolve, reject) => {
    const f1 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('B1')
      }, 0)
      resolve('B2')
    })
    f1.then(res => {
      console.log(res)
    })
    console.log('B3')
    resolve('B4')
  })
}
Fn.then(res => {
  console.log('res')
})
console.log('End')

运行结果:

  • B3
  • End
  • ------ (第一轮宏任务结束) ------- 微任务队列:无 ----- 宏任务队列:setTimeout('B1') ------
  • ----- 执行resolve('B2') ,微任务队列:B2 -----
  • B2
  • ----- 执行resolve('B4') ,微任务队列:B4 -----
  • B4

如果删掉resolve('B2'),运行结果为:

  • B3
  • End
  • ----- 执行resolve('B4') ,微任务队列:B4 -----
  • B4
  • ----- 执行宏任务B1 -----
  • B1