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

  

 

posted @ 2020-02-27 16:00  剑仙6  阅读(792)  评论(0编辑  收藏  举报
欢迎访问个人网站www.qingchun.在线