Promise的使用与方法
Promise的使用与方法
什么是Promise
Promise是一个类,可以翻译成承诺、许诺、期约...
Executor
Executor是创建Promise对象时传入的回调函数,这个回调函数会立即执行,并且传入两个参数
通常会在 Executor中确定Promise的状态:pending、fulfileed(resolved)、rejected
●通过resolve,可以兑现Promise的状态,由 pending 变为 fulfilled 也可以称之为 resolved
○当调用resolve回调函数时,会执行Promise对象的then方法传入的回调函数
●通过reject,可以拒绝Promise的状态,由 pending 变为 rejected
○当调用reject回调函数时,会执行Promise对象的catch方法传入的回调函数
一旦状态被确定下来,Promise 的状态就会被锁死,该状态是不可更改的。如果同时 resolve 和 reject 看谁先调用决定状态
resolve传入不同值的区别
- 一个普通的值或者对象,那么这个值会作为then回调的参数
- Promise对象,那么当前Promise状态会由传入的Promise决定
- thenable对象,会执行该对象then方法,由该对象then调用结果决定Promise状态
then 方法
then方法是Promise对象上的方法,需要通过new Promise创建实例对象调用
它其实是放在Promise的原型上的 Promise.prototype.then,new 操作符会将创建的实例对象的__proto__指向了构造函数的prototype,all方法是类方法,直接通过Promise.all调用
- 接收两个参数
then方法接受两个参数:fulfilled(resolved)的回调函数,当状态变成fulfilled(resolved)时会回调的函数;rejected的回调函数,当状态变成rejected时会回调的函数;
- 多次调用
一个Promise的then方法是可以被多次调用的:每次调用我们都可以传入对应的fulfilled(resolved)回调,当Promise的状态变成fulfilled(resolved)时,这些回调都会被执行
- 返回值
then方法本身是有返回值的,它返回的是一个Promise,这个Promise的状态有如下变化
●当then方法中的回调函数本身在执行的时候,那么它处于pending状态
●当then方法中的回调函数返回一个结果时,那么它处于fulfilled(resolved)状态,并且将结果作为resolve的参数,参数情况同三、resolve传入不同值的区别
●当then方法抛出一个异常时,那么它处于rejected状态
要注意的是,then的连续链式调用,后一个.then对应的是前一个.then返回的Promise,而非最开始的Promise
catch 方法
catch方法也是Promise对象上的方法,同then原理
- 多次调用
一个Promise的catch方法是可以被多次调用的,每次调用我们都可以传入对应的reject回调,当Promise的状态变成rejected时,这些回调函数都会被执行
- 返回值
事实上,catch方法也是会返回一个Promise对象,所以在catch方法后面,我们可以继续调用then方法和catch方法,原理同then方法返回值
finally 方法
finally是在ES9(ES2018)中新增的一个特性:表示无论Promise对象无论变成fulfilled(resolved)还是rejected状态,最终都会被执行的代码;finally方法是不接收参数的,因为无论前面是fulfilled(resolved)状态,还是rejected状态,它都会执行。
resolve 方法
前面的then、catch、finally方法都属于Promise的实例方法,都是存放在Promise的prototype上的;除此之外,还有Promise的类方法,我们可以直接通过类方法来完成Promise的resolve
reject 方法
同resolve方法
all 方法
all方法也是Promise的类方法之一,它的作用是将多个Promise包裹在一起,形成一个新的Promise;新的Promise状态由包裹的所有Promise共同决定:
●当所有的Promise状态变成fulfilled(resolved)状态时,新的Promise的状态为fulfilled(resolved),并且会将所有Promise的返回值组成一个数组
●当有一个Promise的状态为rejected时,新的Promise的状态为rejected,并且将第一个reject的返回值作为参数
allSettled 方法
在all方法中,我们发现有一个缺陷:当有其中一个Promise变成reject状态时,新Promise就会立即变成对应的rejected状态;那么对于resolved的,以及依然处于pending状态的Promise,我们是获取不到对应的结果的。所以在ES11(ES2020)中,添加了新的API Promise.allSettled来解决这个缺陷
注意,allSettled的结果一定是fulfilled,所以结果会在.then中输出
race 方法
当我们需要执行多个Promise,如果有一个Promise有了结果,我们就希望决定最终新Promise的状态,那么可以使用race方法;prace是竞技、竞赛的意思,表示多个Promise相互竞争,谁先有结果,那么就使用谁的结果。
const p1 = new Promise((resolve) => {
setTimeout(()=>{
resolve(1)
},1000)
})
const p2 = new Promise((resolve) => {
setTimeout(()=>{
resolve(2)
},500)
})
const p3 = new Promise((resolve) => {
setTimeout(()=>{
resolve(3)
},1500)
})
Promise.race([p1,p2,p3]).then(res => {
console.log(res) // 2
}).catch(err => {
console.log(err) // 不执行
})
any 方法
any方法是ES12中新增的方法,和race方法是类似的;
●any方法会等到一个fulfilled(resolved)状态,才会决定新Promise的状态;
注意,当等到fulfilled(resolved)状态后,便不再往后输出
const p1 = Promise.resolve(1);
const p2 = Promise.reject(2);
const p3 = Promise.resolve(3);
Promise.any([p1,p2,p3]).then(res => {
console.log(res) // 1(停止,状态不再变更)
}).catch(err => {
console.log(err) // 不执行
})
// reject先行
const p11 = Promise.reject(1);
const p22 = Promise.reject(2);
const p33 = Promise.resolve(3);
Promise.any([p11,p22,p33]).then(res => {
console.log(res) // 等到 3
}).catch(err => {
console.log(err) // 不执行
})
●如果所有的Promise都是reject,那么也会等到所有的Promise都变成rejected状态,并报错AggregateError
const p1 = Promise.reject(1);
const p2 = Promise.reject(2);
const p3 = Promise.reject(3);
Promise.any([p1,p2,p3]).then(res => {
console.log(res) // 不执行
}).catch(err => {
console.log(err) // AggregateError: All promises were rejected
})