await,async,genertor,promise,回调,专题总结

一、回调、promise、generator、await/async都是为了解决异步的方案
二、回调函数的弊端
如果有多层嵌套的回调,就会出现令人恐惧的三角形
在这里插入图片描述
为了解决上面的三角问题,出现了promise
三、promise
promise简单来说就是一个容器,里面保存着某个未来才会结束的时间(通常是一个异步操作的结果),未来使用then获得结果;这样就解决了回调三角形:

下面说明promise是一个容器:
var promise = new Promise(function(resolve, reject) {
// 异步处理
// 处理结束后、调用resolve 或 reject
});
在这里插入图片描述
补充:Promise.all 与 Promise.race的妙用

Promise.all 接收一个数组,数组的每一项都是一个promise对象。当数组中所有的promise的状态都达到resolved的时候,Promise.all的状态就会变成resolved,如果有一个状态变成了rejected,那么Promise.all的状态就会变成rejected(任意一个失败就算是失败),这就可以解决我们并行的问题。调用then方法时的结果成功的时候是回调函数的参数也是一个数组,按顺序保存着每一个promise对象resolve执行时的值。
在这里插入图片描述

看结果不难看出来符合之前所说的

Promise.race 竞速模式 也是接受一个每一项都是promise的数组。但是与all不同的是,第一个promise对象状态变成resolved时自身的状态变成了resolved,第一个promise变成rejected自身状态就会变成rejected。第一个变成resolved的promsie的值就会被使用。
在这里插入图片描述

Promsie.race还有一个很重要的实际用处就是,有时候我们要去做一件事,但是超过三秒钟左右我们就不做了那怎么办?这个时候可以使用Promise.race方法

Promise.race([promise1,timeOutPromise(3000)]).then(res=>{})// timeOutPromise延时3s左右 由于是用setTimeout来实现的并不一定准确3s(一般主线程在开发中不会阻塞3s以上的所以不会有太大问题)这就是我对于Promise的一些基本理解。

promise的then方法获得结果的弊端

如果嵌套多层,那么很多then,也是很可怕的,这是就出现了async和await

我们都知道已经有了Promise的解决方案了,为什么还要ES7提出新的Async/Await标准呢?

答案其实也显而易见:Promise虽然跳出了异步嵌套的怪圈,用链式表达更加清晰,但是我们也发现如果有大量的异步请求的时候,流程复杂的情况下,会发现充满了屏幕的then,看起来非常吃力,而ES7的Async/Await的出现就是为了解决这种复杂的情况。

四、async和await

async和await本质是一种替换promise使用then来获得结果的替代方案
我们常说什么async/await的出现淘汰了Promise,可以说是大错特错,恰恰相反,正因为有了Promise,才有了改良版的async/await,从上面分析就可以看出,两者是相辅相成的,缺一不可。

async和await常用案例

 //获取到城市信息
 getLocation(phoneNum) {
     return axios.post('phoneLocation', {
          phoneNum
      })
  }
  // 点击确定按钮时,获取面值列表(返回值为promise可以用then接受)
  getFaceResult () {
       this.getLocation(this.phoneNum)
           .then(res => {
               if (res.status === 200 && res.data.success) {
                   let province = res.data.obj.province;
                   let city = res.data.obj.city;

                   this.getFaceList(province, city)
                       .then(res => {
                           if(res.status === 200 && res.data.success) {
                               this.faceList = res.data.obj
                           }
                       })
               }
           })
           .catch(err => {
               console.log(err)
           })
   }
   //使用async和await(对于返回promise的方法,可以在前面加一个await来获得结果,而且await下面的方法会等有返回值才执行)
   async getFaceResult () {
       try {
           let location = await this.getLocation(this.phoneNum);
           if (location.data.success) {
               let province = location.data.obj.province;
               let city = location.data.obj.city;
               let result = await this.getFaceList(province, city);
               if (result.data.success) {
                   this.faceList = result.data.obj;
               }
           }
       } catch(err) {
           console.log(err);
       }
   }

更详细的资料:https://segmentfault.com/a/1190000016788484?_ea=4854890

五、Generator函数
①async和await是generator函数的语法糖
②最大特点就是可以交出函数的执行权(即暂停执行)===>异步操作需要暂停的地方,都用 yield 语句注明

function* gen(x){
  var y = yield x + 2;
  return y;
}

上面代码就是一个 Generator 函数。它不同于普通函数,是可以暂停执行的,所以函数名之前要加星号,以示区别。
③generator函数执行方式是调用next函数

var g = gen(1);
g.next() // { value: 3, done: false }
g.next() // { value: undefined, done: true }

上面代码中,调用 Generator 函数,会返回一个内部指针(即遍历器 )g 。这是 Generator 函数不同于普通函数的另一个地方,即执行它不会返回结果,返回的是指针对象。调用指针 g 的 next 方法,会移动内部指针(即执行异步任务的第一段),指向第一个遇到的 yield 语句,上例是执行到 x + 2 为止。

换言之,next 方法的作用是分阶段执行 Generator 函数。每次调用 next 方法,会返回一个对象,表示当前阶段的信息( value 属性和 done 属性)。value 属性是 yield 语句后面表达式的值,表示当前阶段的值;done 属性是一个布尔值,表示 Generator 函数是否执行完毕,即是否还有下一个阶段。

注意点说明!!!通过下面的两套代码返回值,可知。执行next方法后返回的是对象,包含value和done;注意如果next的参数为空,这个返回的对象不会直接复制给yield左边的变量(所以下面的第一套代码y为undefined);注意如果next中有参数的时候,这个参数会作为左边的参数的值(所以下面第二套代码y为2);总言之,如果使用next没有传入参数,此时yield表达式的左边值为undefined;

 function *gen1(x){
    var y = yield x + 2;
    return y;
 }
 var g = gen1(1);
第一套执行:
g.next() // { value: 3, done: false }
g.next() // { value: undefine, done: true }

第二套执行:
g.next() // { value: 3, done: false }
g.next(2) // { value: 2, done: true }

generator实战代码

var fetch = require('node-fetch');

function* gen(){
  var url = 'https://api.github.com/users/github';
  var result = yield fetch(url);
  console.log(result.bio);
}

上面代码中,Generator 函数封装了一个异步操作,该操作先读取一个远程接口,然后从 JSON 格式的数据解析信息。就像前面说过的,这段代码非常像同步操作,除了加上了 yield 命令。

var g = gen();
var result = g.next();

result.value.then(function(data){
  return data.json();
}).then(function(data){
  g.next(data);
});

上面代码中,首先执行 Generator 函数,获取遍历器对象,然后使用 next 方法(第二行),执行异步任务的第一阶段。由于 Fetch 模块返回的是一个 Promise 对象,因此要用 then 方法调用下一个next 方法。

可以看到,虽然 Generator 函数将异步操作表示得很简洁,但是流程管理却不方便(即何时执行第一阶段、何时执行第二阶段)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值