最近,有篇名为 《8张图帮你一步步看清 async/await 和 promise 的执行顺序》 的文章引发了个人关注。前端
做者用一道2017年「今日头条」的前端面试题为引子,分步讲解了最终结果的执行缘由。其中涉及到了很多概念,好比异步的执行顺序,宏任务,微任务等等,同时做者限定了执行范围,以浏览器的 event loop 机制为准。下面是原题的代码:react
async function async1 () { console.log('async1 start'); await async2(); console.log('async1 end'); } async function async2 () { console.log('async2'); } console.log('script start'); setTimeout(function () { console.log('setTimeout'); }, 0); async1(); new Promise(function (resolve) { console.log('promise1'); resolve(); }).then(function () { console.log('promise2'); }); console.log('script end');
紧接着,做者先给出了答案。并但愿读者先行自我测试。面试
script start async1 start async2 promise1 script end promise2 async1 end setTimeout
我在看这道题的时候,先按照本身的理解写出告终果。chrome
script start async1 start async2 promise1 script end async1 end promise2 setTimeout
这里须要先简单地说一些 event loop 的概念。segmentfault
另外,还有 async/await 的概念。promise
再说说我对这道题的理解。浏览器
回过头对比与做者的答案,发现第6和第7行的顺序有问题。babel
再耐心地往下看文章,反复地看了几遍 async1 end 和 promise2 谁先谁后,仍是没法理解为什么在chrome浏览器中,promise2 会先于 async1 end 输出。异步
而后,看到评论区,发现也有人提出了相同的疑惑。@rhinel提出,在他的72.0.3622.0(正式版本)dev(64 位)的chrome中,跑出来的结果是 async1 end 在 promise2 以前。async
随即我想到了一种可能,JS的规范可能会在将来有变化。因而,我用本身的react工程试了一下(工程中的babel-loader版本为7.1.5。.babelrc的presets设置了stage-3),结果与个人理解一致。当前的最新版本 chromeV71,在这里的执行顺序上,的确存在有问题。
因而,我也在评论区给做者留了言,进行了讨论。@rhinel最后也证明,其实最近才发布经过了这个顺序的改进方案,这篇 《Faster async functions and promises》 详细解释了这个改进,以及实现效果。不久以后,做者也在他文章的最后,补充了咱们讨论的结果,供读者参考。
最后,我想说的是,本文虽然只是由一道面试题引伸出的,对浏览器执行顺序的思考、讨论与验证的过程。但正是由于有了这些过程,才让更多的思想得以碰撞,概念进一步得以理解,规范得以明了。
有机会的话,但愿能有与更多的同道,多多交流。
讲道理,async/await 已经出来挺久了,但在近期的面试中,凡是问及异步操做,面试者的回答都仍是 Promise,甚至知道 async/await 都不多,看来还有待进一步普及。并非说 Promise 有什么很差,只是以为 async/await 用着挺爽的,但愿能有更多的人用吧。只有用了,才能进一步理解,产生更多的思考。
因此,这两天翻出了以前写的关于什么是async函数,及其相较于 Promise 的优点。从新整理了一下,原文请前往《细说async/await相较于Promise的优点》。
但愿对你有帮助,也期待进一步的交流,感谢!
PS:欢迎关注个人公众号 “超哥前端小栈”,交流更多的想法与技术。