• ES7之async/await同步编程异步函数


    前言:

    Async/Await应该是目前最简单的异步方案了,ES7 中新增了 async/await 两个关键词
    async顾名思义是“异步”的意思,用于声明一个函数是异步的。而await从字面意思上是“等待”的意思,就是用于等待异步完成。

    主体:

    (1)同步操作

      

       结果为1、3、2,这便是同步状态下的执行顺序

    (2)“async函数关键字”基本用法

      首先了解下async“异步”关键字的返回值,如下所示

      

      这里可以看到函数实际返回Promise {<resolved>: undefined},接下来做下修改,在函数内部加个return

      

      此时返回值为Promise {<resolved>: "测试"}.

    async函数是声明一个异步函数,由此可以分析出async返回值为一个Promise对象。因此我们可以使用then方法添加回调函数,从而处理async函数返回的结果。

      

      上面写法直接return返回一个直接量,等于直接去调用Promise.resove()这个方法。而Promise.resolve方法也就是生成一个Promise实例,并且其直接调用resolve。

      

      上面代码等效写法如下

       

      至此,我们可以得出两个结论:

      1、async函数返回一个 Promise 实例,可以使用then方法(为返回的Promise实例)添加回调函数

      2、如果函数return 一个直接量,那么就等于直接去调用Promise.resolve()方法

       如果上面步骤看着繁琐,那么试下下面的案例,便可以清楚该两个结论

      

       

    (3)awiat“等待”关键字作用

      await是配合async使用的,译为等待,实际为等待async执行结果

      回到之前的案例

      

    之前也说过,如果return返回一个直接量,等于直接去调用Promise.resove()这个方法。而Promise.resolve方法也就是生成一个Promise实例,并且其直接调用resolve。

       上面写法相当于

      或者

      所以可以得出结论三:正常情况下,await命令后面是一个 Promise 对象。当然也可以是原始类型和非Promise对象,但会被转成一个立即resolve的 Promise 对象,这是等同于同步操作。

      接下来测试awiat作用,概括如下

    await必须配合async使用,但是await的对象可以不是Promise对象,一个普通的函数也可以使用。
      1、如果它等到的不是一个 Promise 对象,那 await 表达式的运算结果就是它等到的东西。
      2、如果它等到的是一个 Promise 对象,await 就忙起来了,它会阻塞后面的代码,等着 Promise 对象 resolve,然后得到 resolve 的值,作为 await 表达式的运算结果。
        但是async函数不会造成阻塞,所以await配合async使用,则没有影响到外部。

      1、await等到的Promise对象,但里面没有异步操作,所以不会阻塞

        

      接下来测试下是否阻塞

      

       会看到没有发生阻塞,直接依次执行马上输出1、2、测试1

       2、接下来在Promise里添加异步操作,如下所示

      

       此时结果为,先输出1,,,,然后等待2S后返回async结果后输出2和测试1

      如果之前案例有些繁琐,看看下面这个例子

      

      此外,还可以将async放在IIFE函数里调用,进行案例测试

      

    (4)异常处理

    结论四:如果await后面的异步操作出错,那么等同于async函数返回的 Promise 对象被reject。

      

      捕获错误写法如下:如果await后面的异步操作出错,那么等同于async函数返回的 Promise 对象被reject,所以最好把await命令放在try...catch代码块中。

       

       

    (5)注意点:await关键字只能用于async函数执行上下文中

      

       

     (6)其他案例

      如果之前案例,都看不懂,那么再来个案例

      案例1:

    function p1(){
                return new Promise(function(resolve,reject){
                    setTimeout(function(){
                        console.log("p1_2000");
                        resolve()
                    },3000)
                })
            }
     function p2(){
                return new Promise(function(resolve,reject){
                    setTimeout(function(){
                        console.log("p2_2000");
                        resolve()
                    },2000)
                })
            }
     console.log("start");
     p1();
     p2();
     console.log(end)
     //start 
     //end
     //p2_2000
     //p1_3000

      案例2:接下来做的是让他按这个顺序执行下来咱们就要用到async、await

    function p1(){
                return new Promise(function(resolve,reject){
                    setTimeout(function(){
                        console.log("p1_3000");
                        resolve()
                    },3000)
                })
               
            }
            function p2(){
                return new Promise(function(resolve,reject){
                    setTimeout(function(){
                        console.log("p2_2000");
                        resolve()
                    },2000)
                })
            }
            
            //await 只能出现在异步函数里
             async function shi(){
                console.log("start")
                await p1();
                await p2();
                console.log("end")
             }
             
             p3=shi();
             p3.then(function(){
                 console.log("结束")
             })

      上边函数执行下来就是按照那个顺序下来的,大家记住await 只能出现在异步函数里!配套使用

      案例3:

      

    (7)状态变化

      

       

    (8)优化耗时,同时触发设置

      

       测试上述代码,结果为

    4S后返回“读取数据111”
    在此基础上,再过3S返回“读取数据222”

      两个独立的异步操作(即互不依赖),被写成继发关系(只有执行完one操作,才能去执行two操作)。这样比较耗时,因为只有one完成以后,才会执行two,完全可以让它们同时触发。

      解释:

    解释:这里的one和two方法会返回两个Promise实例(假设是发起Ajax请求,请求one和two的内容),只有执行了方法,对应的操作才会执行,如果写成上面的形式,
    就会导致执行完one的操作后(等待收到服务器的响应后),才能执行two的操作,这样就成了同步,比较耗时,因此可以将上面的写法修改,使得在等待one执行完的时间内
    (在等待服务器响应的期间)去执行执行two

      

       此时结果为同时输出(因为第二个结果耗时短,所以运行完后会一直等待第一个执行,而后一起输出),都是同时触发,这样就会缩短程序的执行时间

      

       上述利用了数组元素解构赋值和Promise.all

      

  • 相关阅读:
    2.5亿!华为成立新公司!
    两年半换第 4 份工作,做个总结
    不懂什么叫编程?
    Google 为什么把几十亿行代码放在一个库?
    IntelliJ 平台 2020 年路线图
    别找了,这是 Pandas 最详细教程了
    MongoDB是什么?看完你就知道了!
    有了这个神器,轻松用 Python 写 APP !
    整理出来几个比较实用的代码对比工具
    学习进度条 第六十一-七十五天 SpringMVC学习笔记
  • 原文地址:https://www.cnblogs.com/jianxian/p/12372602.html
Copyright © 2020-2023  润新知