ES6之Promise对象

145 阅读4分钟

Promise对象其实就是解决异步用的,比回调函数和事件更合理更强大,由ES6写进语言标准,统一了用法,然后提供了原生Promise对象。

两个特点:

对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。

一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。

这边说个东西,我们都知道成功是resolve状态,为什么这边是fulfilled,我查了蛮多的,没有一个有说明,我们可以把这两个理解为一个,甚至直接把fulfilled当做不存在,resolve就是成功。

之前已经分享过了Promise,这边就说一些当初没提到的点。

执行顺序:

var pro = new Promise((resolve, reject) => {

console.log(1);

resolve(2);

});

setTimeout(() => {

console.log(4);

});

pro.then((res) => {

console.log(res);

});

console.log(3);

打印顺序是1324,Promise新建后立即执行,然后then回调是异步的,所以先打印3,之后就是setTimeout和then比较,之前分享过宏任务和微任务,语言标准比宿主环境提供的要快。

Then方法,给实例添加状态改变时的回调函数。then方法的第一个参数是resolved状态的回调函数,第二个参数(可选)是rejected状态的回调函数。then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。

Catch方法,其实也可以直接用then方法写,为了语义化,专门制定错误的回调函数。如果异步操作抛出错误,状态就会变为rejected,就会调用catch方法指定的回调函数。错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个catch语句捕获。不要在then方法里面定义 Reject 状态的回调函数(即then的第二个参数),总是使用catch方法,catch可以捕获前面then方法执行中的错误,如果没有使用catch方法指定错误处理的回调函数,Promise 对象抛出的错误不会传递到外层代码,即不会有任何反应。catch方法返回的还是一个 Promise 对象,因此后面还可以接着调用then方法。如果catch后的then方法报错,不会在上一个catch捕获。

Finally方法,用于指定不管Promise对象最后状态是什么,都会执行。这个方法是ES2018引入标准的。finally方法的回调函数不接受任何参数,这意味着没有办法知道,前面的 Promise 状态到底是fulfilled还是rejected。这表明,finally方法里面的操作,应该是与状态无关的,不依赖于 Promise 的执行结果。

All方法,用于将多个Promise实例变成一个Promise对象。Promise.all方法接受一个数组作为参数,参数都是 Promise 实例,如果不是,就会先调用Promise.resolve方法,将参数转为 Promise 实例,再进一步处理:

const p = Promise.all([p1, p2, p3]);

只有p1、p2、p3的状态都变成resolve,p的状态才会变成resolve,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。

只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

如果作为参数的 Promise 实例,自己定义了catch方法,那么它一旦被rejected,并不会触发Promise.all()的catch方法。

Race方法,跟all差不多,只是参数只要有一个实例率先改变,p的状态就改变,最先改变状态的参数传递给p的回调函数。

Resolve方法,相当于直接声明一个promise然后直接调用resolve方法:

Promise.resolve(‘success’)等价于new Promise(resolve => resolve('success'))

但是这个方法有一些规则:

1、如果参数是Promise对象,就不做任何修改,直接返回;

2、如果是一个thenable对象(有then方法的对象),比如:

let thenable = {

then(resolve, reject) {

resolve();

}

};

会将这个对象转为 Promise 对象,然后就立即执行thenable对象的then方法。

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

4.Promise.resolve()方法允许调用时不带参数,直接返回一个resolved状态的 Promise 对象。

Reject方法,返回一个Promise实例,状态为reject,不管是什么参数,会原封不动的作为reject的参数。

Try方法,这个方法说真的没有很理解,就不分享了。