《前端口试手记》之谈谈promise/async/await的实行递次

👇 内容速览 👇

  • 题目和答案
  • 输出诠释
  • 再谈谈async/await
  • 最新的v8和谷歌浏览器的准确输出

🔍检察悉数教程 / 浏览原文🔍

1. 题目和答案

故事照样要从下面这道口试题提及:叨教下面这段代码的输出是什么?

console.log('script start')

async function async1() {
  await async2()
  console.log('async1 end')
}

async function async2() {
  console.log('async2 end')
}
async1()

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

new Promise(resolve => {
  console.log('Promise')
  resolve()
})
  .then(function() {
    console.log('promise1')
  })
  .then(function() {
    console.log('promise2')
  })

console.log('script end')

上述,在Chrome 66node v10中,准确输出是:

script start
async2 end
Promise
script end
promise1
promise2
async1 end
setTimeout

注重:在新版本的浏览器中,
await输出递次被“提早”了,请看官耐烦逐步看。

2. 流程诠释

边看输出效果,边做诠释吧:

  1. 一般输出script start
  2. 实行async1函数,此函数中又调用了async2函数,输出async2 end。回到async1函数,碰到了await,让出线程
  3. 碰到setTimeout,扔到下一轮宏使命行列
  4. 碰到Promise对象,马上实行其函数,输出Promise。厥后的resolve,被扔到了微使命行列
  5. 一般输出script end
  6. 此时,此次Event Loop宏使命都实行完了。来看下第二步被扔进来的微使命,由于async2函数是async关键词润饰,因而,将await async2后的代码扔到微使命行列中
  7. 实行第4步被扔到微使命行列的使命,输出promise1promise2
  8. 实行第6步被扔到微使命行列的使命,输出async1 end
  9. 第一轮EventLoop完成,实行第二轮EventLoop。实行setTimeout中的回调函数,输出setTimeout

3. 再谈async和await

仔细的朋侪肯定会发明前面第6步,假如async2函数是没有async关键词润饰的一个一般函数呢?

// 新的async2函数
function async2() {
  console.log('async2 end')
}

输出效果以下所示:

script start
async2 end
Promise
script end
async1 end
promise1
promise2
setTimeout

差别的效果就出如今前面所说的第6步:假如await函数背面的函数是一般函数,那末厥后的微使命就一般实行;不然,会将其再放入微使命行列。

4. 实际上是V8引擎的BUG

看到前面,一般人都邑以为真新鲜!(然则根据上面的窍门倒也是能够明白)

但是V8团队肯定了这是个bug(许多强行诠释要被打脸了),详细的PR请看这里。幸亏,这个题目已经在最新的Chrome浏览器中被修复了

简朴点说,前面两段差别代码的运转效果都是:

script start
async2 end
Promise
script end
async1 end
promise1
promise2
setTimeout

await就是让出线程,厥后的代码放入微使命行列(不会再多一次放入的历程),就这么简朴了。

更多系列文章

⭐在GitHub上珍藏/定阅⭐

《前端学问系统》

《设想形式手册》

《Webpack4渐进式教程》

⭐在GitHub上珍藏/定阅⭐

    原文作者:心谭
    原文地址: https://segmentfault.com/a/1190000018622280
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞