首先是一道今日头条的面试题:(据说是今日头条的而且已经烂大街了)javascript
1 async function async1() { 2 console.log( 'async1 start' ) 3 await async2() 4 console.log( 'async1 end' ) 5 } 6 7 async function async2() { 8 console.log( 'async2' ) 9 } 10 11 console.log( 'script start' ) 12 13 setTimeout( function () { 14 console.log( 'setTimeout' ) 15 }, 0 ) 16 17 async1(); 18 19 new Promise( function ( resolve ) { 20 console.log( 'promise1' ) 21 resolve(); 22 } ).then( function () { 23 console.log( 'promise2' ) 24 } ) 25 26 console.log( 'script end' )
这个题我认为的顺序和浏览器的顺序一开始并不同,让我一度觉得浏览器出了问题。java
首先须要了解promise,否则后面就很难理解下去。参见:http://es6.ruanyifeng.com/#docs/promisees6
简单来说若是一个函数前面带了async那么,函数的返回值一定是一个promise的对象。若是返回值不是promise对象,会自动的去包装为一个promise对象。面试
await能够算是async wait简写。等待async执行结果。promise
回到代码中,显而易见首先打印的内容是‘script start’,不须要解释。浏览器
而后就是setTimeout,虽然时间是0可是只有在这一轮事件循环的底部或者是事件队列为空才会当即执行,很明显既不是底部,事件队列也还未执行完成。async
下一个执行到async1();函数
在async1中首先打印‘async1 start’,而后遇到await,await会阻塞后面的代码,先执行async外部的代码,因此会接着打印‘async2’;spa
以前的await中断了当前async的执行,因此下一个执行的就是promise,promise是直接调用同步代码,因此接着就是‘promise1’;code
由于会优先执行同步代码,因此接下来就是打印‘script end’;
执行完毕回到promise接着执行then打印‘promise2’,以后再次回到前面继续执行resolve,可是由于参数为空,因此打印‘undefined’;(promise执行顺序,具体参见:http://es6.ruanyifeng.com/#docs/promise)
这个时候await async2()执行结束,继续async1后面的代码,打印‘async1 end’;
至此因此的事件队列执行结束
前面说了,事件队列为空才会执行setTimeout。
因此正确的顺序为:
script start async1 start async2 promise1 script end promise2 async1 end setTimeout
有错误的话欢迎指正。