理解promise、async 和await之间的执行关系

先看下面的例子node

console.log('script start');
async function async1(){
    console.log('async1 start');
    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');
})

console.log('script end');
复制代码

执行结果以下:git

script start
async1 start
async2 end
Promise
script end
promise1
async1 end
setTimeout
复制代码

注意:在新的浏览器中打印的结果不是这样,是下面的样子github

为何会不同? 咱们先简单说一下是v8团队借鉴了node8中的一个Bug,为了提高性能,在引擎底层将三次tick减小到了2次。可是这样作违反了规范,不过规范也是人制定的,是能够在必定状况下,修改的。传送门,想了解的能够看这里promise

咱们仍是按照规范理解上面的打印结果

  • 1.首先打印出script start (这个就不讲了)
  • 2.执行到async1()的时候,首先会打印出async1 start,由于async表达式定义的函数也是当即执行的
  • 3.而后执行到await async2(),发现saync2也是个async定义的函数,因此直接执行 async2 end,同时async2返回一个Promise,重点:此时返回的Promise会被放入到回调队列中等待,await会让出线程(js是单线程的),接下来跳出async1函数,继续往下执行
  • 4.而后执行到setTimeout,setTimeout是宏任务,会等到执行栈(调用栈)清空以后,微任务所有执行完毕以后,才会去执行,因此setTimeout会被挂起,最后执行
  • 5.而后到了new Promise,new Promise是当即执行的,因此会当即打印出Promise;(Promise是一个当即执行的函数,可是它的成功(resolve())或失败(reject())回调函数确实一个异步执行的回调。) 而后执行resolve()的时候,resolve()这个任务会被放入回调队列中,等到调用栈有空闲的时候,事件循环(Event Loop)再来取走它, 这时候会跳出Promise,继续往下走
  • 6.输出script end;
  • 7.同步任务已经所有执行完毕,执行栈如今已经空闲出来,那么事件循环就会去回调队列中取任务继续放到执行栈中执行;
  • 8.这时候取的第一个任务就是async2放进去的Promise,执行Promise的时候遇到了resolve函数,resolve又回被放入到任务队列中继续等待,而后再次跳出async1 继续下一个任务
  • 9.接下来取走的就是new Promise放进去的resolve回调,这个被调用栈执行,并输出promise1,而后继续取下一个任务
  • 10.此次终于取到了那么Promise的resolve回调,由于async2并无return内容,因此这个resolve的参数是undefined,此时await定义的Promise已经执行完毕而且返回告终果,因此能够继续往下执行async1函数后面的任务了,因而输出async1 end
  • 11.上面的微任务执行完毕以后,开始执行宏任务中的异步setTimeout

总结:Event Loop 执行顺序以下:

  • 1 首先执行同步任务,这属于宏任务
  • 2.当执行完全部同步任务代码以后,执行栈为空,查询是否有异步代码须要执行
  • 3.执行全部微任务
  • 4.当执行完全部微任务后,若是有必要会渲染页面
  • 5.而后开始下一轮的Event Loop,执行宏任务中的异步代码,也就是setTimeout中的回调函数

宏任务:

  • 1.script
  • 2.setTimeout
  • 3.setInterval
  • 4.setImmediate
  • 5.I/O
  • 6.UI rendering

微任务:

  • 1.process.nextTick(node 独有)
  • 2.promise
  • 3.MutationObserver
相关文章
相关标签/搜索