Promise&&Async/Await面试题解答

130 阅读2分钟

前言

最近看到了比较多的Promise题目,主要考查的就是对事件循环的一个理解和掌握程度,事件循环的讲解,因为JavaScript是分为同步和异步执行,所以就会出现后面的代码比前面的代码先执行,我们通过几道题目来学习类似的面试题。

宏任务和微任务的执行顺序

这类型的题目我们都需要拆解成三个部分

  1. 同步执行的代码
  2. 微任务
  3. 宏任务
console.log('script start');

setTimeout(function() {
  console.log('setTimeout')
}, 0);

Promise.resolve().then(function() {
  console.log('promise1');
  setTimeout(function() {
    console.log('promise1 setTimeout');
  }, 0);
})

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

console.log('script end');

通过拆分多个步骤来解析执行顺序 定义两个数组 宏任务:[ ] 微任务:[ ]

第一步

  1. console.log('script start') 为同步代码直接执行输出 script start
  2. 然后遇到了一个定时器,所以需要把定时器中的回调函数添加到宏任务中 宏任务:[]
[
  console.log('setTimeout')
]
  1. 然后进入一个立即成功的Promise中把这段代码添加到微任务中
[
  console.log('promise1');
  setTimeout(function() {
    console.log('promise1 setTimeout');
  }, 0);
]
  1. 接下来还是一个Promise,同上操作,添加到微任务中
[
  console.log('promise1');
  setTimeout(function() {
    console.log('promise1 setTimeout');
  }, 0);
  ,
  console.log('promise2');
]
  1. 最后console.log('script end') 为同步代码直接执行输出 script end

第一次执行结束了,接下来执行微任务中的代码,再执行宏任务的代码

  1. 首先执行console.log('promise1');, 遇到定时器就添加到宏任务中
[
  console.log('setTimeout')
  ,
  console.log('promise1 setTimeout')
]
  1. 执行console.log('promise2');
  2. 现在微任务队列任务全部执行完毕,宏任务中还有两个任务,依次执行
// 最后我们得到的结果就是
script start
script end
promise1
promise2
setTimeout
promise1 setTimeout

Async/Await

es7中加入了async/await, 是一个语法糖,解决回调地狱问题

await new Promise(reslove => {
  resolve('完成')
})
console.log('end')

同等于

new Promise(reslove => {
  resolve('完成')
}).then(res => {
  console.log('end')
})

可以理解成await后的Promise成功了之后,后续的代码就放到微任务中就可以了,再结合宏微任务的执行顺序,基本就可以解决大部分Promise输出顺序的面试题,看一个例子吧

console.log('start')

async function async1() {
  console.log('async1 start')
  await async2()
  console.log('async1 end') // 这一行代码在async2这个Promise成功后添加到微任务中
}

async function async2() {
  console.log('async2 start')
  return new Promise(resolve => {
    resolve()
    console.log('async2 end')
  })
}

async1()
  1. 输出 start
  2. async1 start
  3. 执行async2函数
  4. 输出 async2 start
  5. async2 end
  6. Promise成功 同步代码结束
  7. 微任务还有一个async1 end输出完结束