• 详解promise、async和await的执行顺序


    1、题目和答案

    一道题题目:下面这段promise、async和await代码,请问控制台打印的顺序?

    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')

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

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

    2、知识点

    显然,这考察的是js中的事件循环和回调队列。注意以下几点:

    Promise优先于setTimeout宏任务。所以,setTimeout回调会在最后执行。
    Promise一旦被定义,就会立即执行。
    Promise的reject和resolve是异步执行的回调。所以,resolve()会被放到回调队列中,在主函数执行完和setTimeout前调用。
    await执行完后,会让出线程。async标记的函数会返回一个Promise对象

    3、 难点

    最令人困惑的,就是async1 endpromise2之后输出

    async 函数中可能会有 await 表达式,这会使 async 函数暂停执行,将await的结果封装成一个Promise,并等待解析完成后继续执行,
    另外如果await 遇上async函数,阮一峰老师这么说明:
    async 函数返回一个 Promise 对象,当函数执行的时候,一旦遇到 await 就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句。

    在函数async1中,执行promise由于async2async标记的函数,所以默认返回promise对象)会发现resolve(),然后放入回调队列。

    接着执行下方的new Promise中的resolve()输出promise2,再回来输出async1 end

    其中,async1函数可以写成以下方式(便于理解):

    async function async1(){
      console.log('async1 start')
      async2().then( _ => {
        console.log( 'async1 end ')
      })
    }

    3、流程

    1. console.log('script start')输出:script start
    2. setTimeout被放在最后调用
    3. 执行async1函数,输出async1 start。然后,进入async2函数,输出async2,并返回Promise对象。回到async1,由于await,让出线程,async2函数返回的Promise放在回调队列
    4. 新new了一个Promise对象,输出promise1。其中的resolve()被放在回调队列。
    5. console.log('script end')输出:script end
    6. 执行回调队列中,async1返回的Promise对象,对象产生的resolve被放入对调队列。这里不输出任何值。
    7. 执行回调队列中,下方Promise显式声明的resolve,输出promise2
    8. 执行回调队列中,由于async1函数返回的promise对象的resolve,输出async1 end
    9. 执行回调队列中,最后的setTimeout,输出setTimeout
    10. finish



    作者:心谭
    链接:https://www.jianshu.com/p/5938d9fdbccd
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 相关阅读:
    数据库连接池的最小连接为什么是Idle语义
    mybatis多个参数不加@Param
    uboot中使用延迟函数
    uboot中linker list数据结构
    Linux内核启动流程
    安卓系统出现时间强制设置为固件编译时间的问题
    MMC/SD卡介绍
    蓝牙博文记录
    混合编程杂谈
    转载:互联网协议入门
  • 原文地址:https://www.cnblogs.com/xiaolucky/p/12192730.html
Copyright © 2020-2023  润新知