首先来看一道考察JS执行机制的面试题,原题是今日头条的前端面试题,我稍微进行了一点改造:html
async function async1() { console.log( 'async1 start' ) await async2() console.log( 'async1 end' ) } async function async2() { new Promise( function ( resolve ) { console.log( '11' ) resolve(); }).then( function () { console.log( '22' ) }) } 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 11 promise1 script end 22 promise2 async1 end setTimeout
由于题目是变幻无穷的,平常开发中的状况也是多种多样的,正确理解了其中的执行规律才能更好地开发,固然若是你获得的结果是同样的而且可以自圆其说那也就不必看下去了,若是你还对这个结果有点懵那就听听个人理解吧。node
事实上,咱们的JS代码用同步和异步这两种划分方式来决定执行的前后顺序显然是不够的,从而有了另外一种划分方式,具体谁提出来的我就没考证了,大致上你们是这样分的:面试
由于咱们上面的面试题是前端面试题,因此咱们讨论的都是浏览器环境下的表现,node环境下的event loop貌似有些不同,这里就不讨论了。segmentfault
既然前端谈到了JS是单线程的,同时只能处理一个任务,而咱们又将各类各样的任务分为了宏任务和微任务,那到底哪一种任务先执行了,这个运行逻辑就是event loop的判断逻辑。promise
先说说个人理解,再来印证上面代码的运行顺序:浏览器
说回上面的面试题,咱们模拟event loop来首先给他们归个队多线程
async本质上是加上了Generator函数而且内置了执行器的一个语法糖,而且async函数返回的是Promise对象。惟一须要注意的是await后面不管接的是同步代码仍是异步代码都要等他们执行完毕才能执行await结果以后的代码。而且通过验证,当遇到await语句时是从右到左先执行的await后面的代码,而后才交出线程的控制权直到await等待的结果运行完毕。异步
整体上,算是能对上面那个题目的执行过程有了一个能自圆其说的解释,只是吧,为何规则是这样的呢?这些规则怎么证伪呢?这是我查资料的时候最纠结的问题。后来跟同事交流了以后吧,以为也不必纠结,毕竟最终的解释器是C写的,不懂规则能够去看源码啊,但是我看不懂啊,哈哈。。。因此,既然你们大部分人都是这么说,也能说得通,暂且先记着吧,至少,仍是可以解释平常中形形色色代码的运行规律的。async
看了几篇不一样观点的文章以后从新梳理一下event loop的顺序:
参考文章中有几篇文章比我讲的生动一些,没看懂的能够参考一下,我主要是梳理一下本身的理解,有不一样想法的欢迎交流。