一篇文章,搞懂promise,async await的区别及使用

1、promise

es6新增一种语法
为了解决异步编程的一种方式 主要用于替代回调函数获取异步执行的结果
面向对象的方式进行封装 构造函数Promise

(1)创建实例对象

 // 创建一个实例对象
 var promise实例 = new Promise(function(){})  
 或者
 var promise实例 = new Promise(()=>{})
// 利用这个实例对象身上的属性和方法解决开发中的问题

创建一个promise实例
在创建promise实例的时候,构造函数需要接受一个参数 ,这个参数必须是一个函数类型。可以是一个普通函数 也可以是一个箭头函数,通过console.log(promise实例)查看如图所示。

在实例p1中可以查看到,实例对象类型是promise,它自身默认原型上面有catch()、finally()、then()

(2)promise实例的状态
每创建一个promise实例 每一个实例都会有一个状态 promiseState
实例状态分为三种状态

  • pending 等待,刚创建出来的实例状态就是pending。
  • fulfilled 成功,调用resolve方法之后的状态。
  • rejected 失败,调用reject方法之后的状态。

promise的传入回调函数里面 自带两个形参 resolve(实例状态为成功) 和 reject(实例状态为失败)
这两个形参 resolve和reject是一个函数
当我们在promise的函数内部调用resolve的时候 此时这个实例的状态就会变为成功
当我们在promise的函数内部调用reject的时候 此时这个实例的状态就会变为失败

每一个创建出来的实例都会有一个结果
如果实例状态是成功的,那么这个结果被称为终值 value, 成功的结果是在调用resolve函数的时候传递的参数 只能传递一个参数。
如果实例状态是失败的,那么这个结果被称为拒因 reason, 失败的结果是在调用reject函数的时候传递的参数 只能传递一个参数。
如是传递的参数超过1个,只会默认第一个为可以传递的参数。
注意:
一个promise实例最终有一个状态,状态一旦确定就不允许再次改变,也就是说要么成功,要么失败
在这里插入图片描述

案例:
在这里插入图片描述

(3)实例的原型上面都有三个方法
每一个实例的原型上面都有三个方法,它们内部是一个回调函数。

 then(function(res){console.log(res,'调用了')});
 catch(function(error){});
 finally(function(){});

三个方法每一个都需要传递一个回调函数

  • 当一个实例成功的时候就会执行then里面回调函数
  • 当一个实例失败的时候就会执行catch里面回调函数
  • 无论实例成功还是失败都会执行finally里面的回调函数

实例成功的时候会有一个结果 叫做终值 终值是在调用成功resolve函数时候传递 可以在then的回调函数里面获取。
关于参数
调用resolve函数其实就是相当于调用then传递的回调函数,resolve里面传递的实参可以在then的回调函数形参里面接收。
调用reject函数就相当于调用catch里面的回调函数,调用reject传递实参可以在catch回调函数形参接收。
finally方法会接收一个函数,这个函数无论在成功还是失败都会调用。回调函数不接收参数。

(4)promise的作用
结合之前的ajax封装的函数,将其ajax函数内部的回调函数给替代掉,获取异步返回的结果。
流程:
在ajax函数内部先创建一个promise的实例,再创建一个实例p1。
通过实例的属性和方法来解决发送数据给后端的问题,配置信息、请求方式、地址等相关配置。并进行判断请求方式给予对应的方式发出请求、获取后端的数据。
在load函数里面可以得到后端返回的结果,调用resolve函数传递后端返回的结果,将结果当成终值。添加一个error函数,当出错的时候就被调用,函数内部调用reject函数,提示出错。
最后返回一个实例p1。
让前端通过调用ajax函数得到其返回的一个promise实例。因为只要是promise实例就有三个原型方法,只要实例状态成功,就会调用then的回调函数,在then的回调函数内部就可以接收到成功的终值。若实例状态失败,就会调用catch的的回调函数。
案例:
在这里插入图片描述

(5)回调嵌套地狱的问题

  • 1、问题1
    有a,b,c三个请求 c请求需要传递两个参数 第一个参数是a请求的返回值 第二参数是b请求返回值
    2、分析:

  • 因为每一个请求都是异步的 必须保证一个请求回来了再发送另一个请求。

  • 需要在一个请求回调函数里面发送另一个请求,这样导致了回调函数出现嵌套的问题。层级逐步嵌套, 如果嵌套层级过深,出现横向滚动条

  • 那么就会导致代码阅读起来不方便。

  • 在这里插入图片描述

  • 使用promise方式 本身封装的ajax里面没有了回调函数 但是promise本身自带的then里面需要传递一个回调函数,所以并没有彻底解决回调嵌套的问题。
    在这里插入图片描述

async和await

(1)async
为了进一步解决这个问题在一个函数前面可以加上async修饰符。es7提出
无论是普通函数还是箭头函数都可以,只要函数被async修饰之后,js执行这个函数的时候会当成异步的函数。
凡是带有async修饰的函数 返回值是一个promise实例,即使我们自己添加了返回值,这个函数返回值得到还是一个promise实例,此时我们自己添加的返回值,会当成promise实例的终值(promiseresult=返回值),promiseState为fullfiled。
注意 async函数内部diamagnetic还是同步的,而其生成的promise实例的then方法输出是异步的。
在这里插入图片描述

async修饰符案例:
在这里插入图片描述

(2)wait
只能等待一个promise实例,会等待这个promise执行完结束,拿到promise实例的终值。
在没有await之前获取实例成功的结果,必须要用then的回调函数去获取,因为then本身自带了回调函数,这样还会导致回调函数嵌套。
而:

const 终值 = await promise实例
  • 使用await来获取promise实例成功的结果,p1实例不管多久有结果,wait都会等待。
  • 直到得到promise的实例p1成功的结果也就是终值。这样await后面所有代码都可能被阻塞
  • 所以js在执行的时候会报一个错误“ await is only valid in async functions and the top level bodies of modules ”。
  • await不能直接这样使用,使用的时候必须嵌套在带有async修饰的函数内部。就解决后面代码会被阻塞的问题。

wait注意问题:

  • await只要实例是出于pending状态,都会等待,但是无法拿到失败的结果,只能拿到成功的结果。
    那么需要使用try…catch代码块来实现。

try…catch代码块

一般用于测试不确定的代码,若不用try…catch ,代码出现报错的时候后面就不会执行了。


 try {
         const res = await p1
          // 将一些可能会出错的代码放在此处,一旦报错就会执行catch里面的代码.
        //也还会正常往下执行
        // 如果不报错就正常往下执行
        console.log(res)
       } catch (error) {
        console.log(error)
       }

案例
在这里插入图片描述

使用await和async彻底解决回调嵌套地狱的问题(面试)

思路:

  • 使用async修饰的函数,在函数内部通过wait获取promise实例的成功结果,就不需要使用then的回调函数。先发送第一个请求,登录,等待第一个请求得到成功结果,再依次执行第二个请求、登录,依次执行。

  • 属于局部同步执行方式。

  • 这样在执行异步函数的时候不会等待这个函数执行结束,就会直接执行后面的代码 后面的代码就不会被阻塞。但是在异步函数的内部代码又是按照顺序执行

  • 请求会一个一个发送出去。不影响外部全局同步。
    在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值