promise几个容易混淆的方法

511 阅读3分钟

这是我参与11月更文挑战的第17天,活动详情查看:2021最后一次更文挑战

问题

面试官:promise都有经常用,那你能讲讲它的allSettled方法吗?

面试者:这个方法是属于他的静态方法,挂载在Promise上的,他接受一组promise对象,只要这组promise对象状态有一个变了,就会执行它的then方法。

面试官: 你讲的好像是它的race方法。

面试者: 尴尬。。。

promise有几个方法不经常用的话,经常会搞混,今天来总结下它们的区别。

promise

promise实例上的then,catch方法,这几个一般不会混淆。

混淆的主要是实例上的finally方法,静态方法all, race,allSettled,any方法。

实例方法

finally

finally方法不管promise的状态如何,一旦状态由pending变了(比如fulfilled或者rejected),都会执行finally方法。回调函数没有参数返回。执行后返回promise对象。

new Promise((resolve,reject) => {
  resolve('resolve')
}).finally(() => {console.log('finally函数被执行了')})

new Promise((resolve,reject) => {
  reject('reject')
}).finally(() => {console.log('finally函数被执行了')})

静态方法

all

all方法的参数可选,但是必须是具有iterator接口,一般是数组,然后数组里的每一项是promise对象,如果是其他类型,会调用Promise.resolve转成promise对象。执行all后返回promise对象。

只有当参数里的所有项的状态都变成fulfilled,all返回的promise对象的状态才变成fulfilled,返回值是所有项的返回值组成的数组

只要参数里有一项变成rejected,all返回的promise对象的状态就变成rejected, 返回值就是那一项的返回值。

Promise.all([1,2,3,4]).then((res) => {
    console.log(res) // [1,2,3,4]
})

Promise.all([1,2,Promise.reject(1),4]).then((res) => {
    console.log(res) 
}).catch((err) => {
    console.log(err) // 1
})

race

race方法的参数跟all的一样,需要具有iterator接口,返回的是promise对象。

它和all不同的是:

只要参数里的任意项先改变状态,race的状态就变成它的状态(如果是rejected就是rejected,如果是fulfilled就是fulfilled),后续其他项的状态不会再影响race的状态。然后就执行对应的回调函数(then或者catch等)。回调函数的参数就是那一项的返回值。

Promise.race([Promise.resolve('then'),Promise.reject('reject'),3,4]).then((res) => {
    console.log('then:', res) 
}).catch((err) => {
    console.log('err:',err) 
})
// then: then


Promise.race([Promise.reject('reject'),Promise.resolve('then'),3,4]).then((res) => {
    console.log('then:', res) 
}).catch((err) => {
    console.log('err:',err) 
})
// err: reject

allSettled

和all和race的传参一样,需要具有iterator接口,返回的是promise对象。

不一样的是,allSettled总是要等到参数里的promise的状态全部发生改变之后,才会执行后面的回调函数,而且不管参数的promise变成fulfilled还是rejected状态,allSettled的状态只会是fulfilled

Promise.allSettled([Promise.reject('err'),new Promise((resolve, reject) => {
  setTimeout(reject.bind(null, 'err'), 2000)
}), 4]).then((res) => {
    console.log(res)  
    // [
    //    {status: 'rejected', reason: 'err'},  
    //    {status: 'rejected', reason: 'err'}, 
    //    {status: 'fulfilled', value: 4}
    // ]
    })

回调参数如果状态是fulfilled则会有value字段,如果是rejected则会有reason字段。 对应的是allSettled参数的promise对象的返回值。

any

和all和race,allSettled的传参一样,需要具有iterator接口,返回的是promise对象。

不一样的是,any方法的状态是所有参数的promise都变成rejected才会变成rejected,否则只要有一个promise是fulfilled,它的状态就是fulfilled。回调参数就是fulfilled的promise的返回值。

Promise.any([
    Promise.reject('err1'),
    Promise.reject('err2'), 
    Promise.reject('err3')
]).catch((err) => {
    console.log(err)  // AggregateError: All promises were rejected
})

Promise.any([
    Promise.reject('err1'),
    Promise.resolve('resolve'), 
    Promise.reject('err2')
]).then((res) => {
    console.log(res)  // resolve
})