ES6---Promise

在JavaScript的世界中,所有代码都是单线程执行的。由于这个“缺陷”,导致JavaScript的所有网络操作,浏览器事件,都必须是异步执行

为了更好的解决异步编程,ES6中新提供了Promise的解决方案。

语法上说,Promise 是一个对象,从它可以获取异步操作的消息。

最近研究之前项目前端登录功能代码中遇到了Promise这个点很陌生,下面也一起学习记录一下

Promise 状态

1.pending(进行中)
2.fulfilled(已成功)
3.rejected(已失败)

Promise 对象只有:从 pending 变为 fulfilled 和从 pending 变为 rejected 的状态改变。只要处于 fulfilled 和 rejected ,状态就不会再变了即 resolved(已定型)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。成功的结果数据一般称为value,失败的结果数据一般称为reason

Promises初步使用

下面先简单的使用一下看看具体是怎么回事吧
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以通过上面的小demo清楚的看到,我们首先创建了一个promise对象,且它有两个参数 resolve reject,这两个参数也是函数resolve执行后返回promise的成功状态,此时 Promise对象状态从pending变为fulfilled,reject执行后返回promise的错误状,此时 Promise对象状态从pending变为rejected。然后通过调用promise实例的then方法获取resolve和reject传递的结果。同时我们在最后面打印了一句话来证明promise是异步的,当我们的代码没有执行完的时候,就已经打印成功。以上我们就对promise有了一个初步的认识。

Promises产生的原因及解决的问题

在ES5的时候,比如我们想完成一个功能A异步函数接口的一个参数需要从B异步函数接口获取,而B接口的参数又需要从C异步函数接口获取。正常情况下会把接口写在另一个接口的回调里,使用纯回调函数的方式来解决这个问题。但是随着嵌套深度就会造成一定的逻辑混乱和异常的难以处理,而且极度影响性能和用户体验。这就是我们常说的回调地狱!而ES6为了很好的解决这个问题,promise应运而生因为promis支持链式调用。在ES7中有了新的async/await解决起来更加方便高效成为了目前回调地狱的终极解决方案。

API

(1) Promise.all(iterable)

iterable 必须是一个可迭代对象,如 Array 或 String。方法用于将多个Promise实例包装成一个新的Promise实例

const pro1 = new Promise((resolve,reject) => {
    resolve(1)
})
const pro2 = Promise.resolve(2)
const pro3 = Promise.resolve(3)
const pro4 = Promise.reject(4)
const proAll = Promise.all([pro1,pro2,pro3,pro4])
const proAll2 = Promise.all([pro1,pro2,pro3])
proAll.then(
    values => {
        console.log("成功",values)
    },
    reason => {
        console.log("失败",reason)
    }
)

在这里插入图片描述
只要pro1、pro2、pro3、pro4之中有一个被rejected,proAll的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
只有所有pro的状态都变成fulfilled,proAll的状态才会变成fulfilled,此时pro1、pro2、pro3、pro4的返回值组成一个数组,传递给proAll的回调函数。

注意,如果作为参数的 Promise 实例,自己定义了catch方法,那么它一旦被rejected,并不会触发Promise.all()的catch方法。引用阮一峰官网的一个例子:

onst p1 = new Promise((resolve, reject) => {
  resolve('hello');
})
.then(result => result)
.catch(e => e);

const p2 = new Promise((resolve, reject) => {
  throw new Error('报错了');
})
.then(result => result)
.catch(e => e);

Promise.all([p1, p2])
.then(result => console.log(result))
.catch(e => console.log(e));
// ["hello", Error: 报错了]

上面代码中,p1会resolved,p2首先会rejected,但是p2有自己的catch方法,该方法返回的是一个新的 Promise 实例,p2指向的实际上是这个实例。该实例执行完catch方法后,也会变成resolved,导致Promise.all()方法参数里面的两个实例都会resolved,因此会调用then方法指定的回调函数,而不会调用catch方法指定的回调函数。
如果p2没有自己的catch方法,就会调用Promise.all()的catch方法。

(2) Promise. race(iterable)

就像它的名字一样,赛跑如果将上述代码换为race,只要pro1、pro2、pro3、pro4之中有一个实例率先改变状态,proAll的状态就跟着改变。那个率先改变的Promise实例的返回值,就传递给prroAll的返回值。all是等所有的异步操作都执行完了再执行then方法,那么race方法就是相反的,谁先执行完成就先执行回调。race的使用比如可以使用在一个请求在10s内请求成功的话就走then方法,如果10s内没有请求成功的话进入reject回调执行另一个操作。

(3) Promise.resolve(value)
如果我们希望将一个现有对象转化为Promise对象,我们就可以使用Promise.resolve()方法。根据参数的不同可以分为4种情况:
(1)参数是一个Promise实例
  如果参数是Promise实例,那么Promise.resolve将不做任何修改、原封不动地返回这个实例。
(2)参数是一个thenable对象
  如果参数是一个thenable对象,即具有then()方法的对象,那么Promise.resolve()就会将该对象立即转化成 Promise对象那个,并立即执行then方法。

let thenable = {
  then: function(resolve, reject) {
    resolve(42);
  }
}

let p = Promise.resolve(thenable);

p.then(function(value) {
  console.log(value);
})

(3)参数不是具有then方法的对象,或根本就不是对象

如果参数是一个原始值,或者是一个不具有then方法的对象,则Promise.resolve方法返回一个新的Promise对象,状态为Resolved。

(4)不带有任何参数

(4) Promise.reject(reason)

Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为rejected。

实例方法

(1)Promise.prototype.then()
它的作用是为 Promise 实例添加状态改变时的回调函数。then方法的第一个参数是resolved状态的回调函数,第二个参数(可选)是rejected状态的回调函数。then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。
(2)Promise.prototype.catch()
Promise.prototype.catch()方法实际上是then(null, rejection)方法的别名, 这里使用catch()纯粹是为了便于使用和理解。它会返回一个Promise,并且处理拒绝的情况。它的行为与调用Promise. prototyp e .then(undefined, onRejected)相同。之前说then()方法接受两个参数,第一个参数是pending变成resolved之后执行的函数,它是必选的; 第二个参数是pending变成rejected之后执行的函数,它是可选的。但是建议使用catch因为使用catch还可以捕获在then方法执行中存在的错误。

promise
  .then(function(data) { 
    // success
  })
  .catch(function(err) {
    // error
  });

(3)Promise.prototype.finally()

就理解为javafinally代码块就可以不管是成功还是失败finally中都会执行

还有很多细节问题过后补充

发布了29 篇原创文章 · 获赞 11 · 访问量 1861

猜你喜欢

转载自blog.csdn.net/chihaihai/article/details/103401711
今日推荐