前言
在工作中虽然使用了很久的Promise,但是里面的一些细节还是有些迷糊,特写一篇博客来记录Promise的使用细节。
Promise 的三种状态
pedding:初始化状态fulfilled:成功时状态rejected: 失败时状态 需要注意的是,Promise是不可逆的,只能由pedding到fulfilled或者由pedding到rejucted
Promise resolve参数
Promise中resolve传递的参数分为三种情况
- 一个普通的值或者对象,那么这个值或者参数就作为
then回调的参数
const promise = new Promise((resolve,reject) => {
resolve(123)
}).then(res => {
console.log(res) // 123
},err => {
console.log(err)
})
- 一个新的
Promise,那么这个新的Promise的状态会决定原来Promise的状态
// 新的Promise调用resolve
const p1 = new Promise((resolve,reject) => {
resolve(new Promise((resolve,reject) => {
resolve(123456)
}))
}).then(res => {
console.log(res) // 123456
},err => {
console.log(err)
})
// 新的Promise调用reject
const p2 = new Promise((resolve,reject) => {
resolve(new Promise((resolve,reject) => {
reject(123456)
}))
}).then(res => {
console.log(res)
},err => {
console.log(err) // 123456
})
- 一个实现了
then方法的对象,那么这个对象称为thenable对象,会自动执行这个then方法,根据then方法的结果来决定原来Promise的状态
// thenable对象调用resolve
const p1 = new Promise((resolve,reject) => {
resolve({
then(resolve,reject){
resolve(123456)
}
})
}).then(res => {
console.log(res) // 123456
},err => {
console.log(err)
})
// thenable对象调用reject
const p2 = new Promise((resolve,reject) => {
resolve({
then(resolve,reject){
reject(123456)
}
})
}).then(res => {
console.log(res)
},err => {
console.log(err) // 123456
})
then方法返回值
和上面resolve的参数一样,then方法也会返回三种类型的值:
- 普通的值或者对象,将作为下一个
then回调的参数
new Promise((resolve,reject) => {
resolve(123)
}).then(res => {
return 456
}).then(res => {
console.log(res) // 456
})
- 一个新的
Promise,那么这个新的Promise的状态将会决定下一次回调的是then还是catch
new Promise((resolve,reject) => {
resolve(123)
}).then(res => {
return new Promise((resolve,reject) => {
resolve(456)
})
}).then(res => {
console.log(res) // 456
})
new Promise((resolve,reject) => {
resolve(123)
}).then(res => {
return new Promise((resolve,reject) => {
reject(456)
})
}).catch(err => {
console.log(err) // 456
})
- 一个
thenable对象,thenable对象的状态决定下一次回到的是then还是catch
new Promise((resolve,reject) => {
resolve(123)
}).then(res => {
return ({
then(resolve,reject){
resolve(456)
}
})
}).then(res => {
console.log(res) //456
})
new Promise((resolve,reject) => {
resolve(123)
}).then(res => {
return ({
then(resolve,reject){
reject(456)
}
})
}).catch(err => {
console.log(err) //456
})
注意:当then抛出异常的时候,状态将会变成rejected
new Promise((resolve,reject) => {
resolve(123)
}).then(res => {
throw new Error("抛出异常")
}).catch(err => {
console.log(err) // Error: 抛出异常
})
catch方法返回值
同then返回的返回值一样,有三种情况
- 返回一个普通的值或者对象,将作为下一个
then回调的参数 - 返回一个新的
Promise,根据返回的Promise的状态来决定 - 返回一个
thenable对象,根据thenable对象的状态来决定 如果抛出异常,则下一次还是catch回调
finally方法
finally是ES9中新增的一个方法,无论Promise的状态是fulfilled还是rejected,最终都会被执行,此方法不需要接受参数
new Promise((resolve,reject) => {
resolve(123)
}).then(res => {
console.log(res) // 123
return new Promise((resolve,reject) => {
reject(456)
})
}).catch(err => {
console.log(err) // 456
}).finally(() => {
console.log("finall执行")
})
上面的then catch finally 属于Promise的实例方法,存放于Promise的prototype上,下面来看一下Promise的类方法
Promise.resolve()
相当于new Promise,并调用了resolve方法,接收的参数同上面一样,这里不过多赘述,并将Promise的状态改为fulfilled
Promise.resolve(123).then(res => {
console.log(res) // 123
})
Promise.reject()
reject方法类似于resolve,只是将Promise的状态转换为rejected
Promise.reject(123).catch(err => {
console.log(err) // 123
})
Promise.reject无论传递什么参数,都会作为catch回调的参数
Promise.reject(new Promise((resolve,reject) => {
resolve(123)
})).then(res => {
console.log(res)
}).catch(err => {
console.log(err) // Promise {123}
})
Promise.all()
它的作用是将多个Promise包裹在一起,形成一个新的Promise,新的Promise将由包裹的所有的Promise决定
- 当所有的
Promise都是fulfilled时,新的Promise的状态就是fulfilled,并且会将所有Promise的结果放在一个数组中 - 一旦有一个
Promise的状态为rejected,不会继续执行其他的Promise,新的Promise的状态就是rejected,并且返回第一个状态为rejected的Promise的结果
const p1 = Promise.resolve(123)
const p2 = Promise.resolve(456)
const p3 = Promise.resolve(789)
Promise.all([p1,p2,p3]).then(res => {
console.log(res) // [123,465,789]
})
const p4 = Promise.reject('reject')
Promise.all([p1,p2,p3,p4]).catch(err => {
console.log(err) // reject
})
Promise.allSettled()
Promise.all()方法有一个缺陷,当有一个Promise的状态为rejected时,新的Promise会立马变成rejected状态,对于处于fulfilled的Promise是拿不到结果的
- ES11中新增了
Promise.allSettled()方法,该方法会等到所有包裹的Promise都有结果,无论包裹的Promise的结果是fulfilled还是rejected,才会有最终的形态 - 新的
Promise的状态是fulfilled
const p1 = Promise.resolve(123)
const p2 = Promise.resolve(456)
const p3 = Promise.resolve(789)
Promise.allSettled([p1,p2,p3]).then(res => {
console.log(res) /* [
{ status: 'fulfilled', value: 123 },
{ status: 'fulfilled', value: 456 },
{ status: 'fulfilled', value: 789 }
]*/
})
const p4 = Promise.reject('reject')
Promise.allSettled([p1,p2,p3,p4]).then(res => {
console.log(res) /* [
{ status: 'fulfilled', value: 123 },
{ status: 'fulfilled', value: 456 },
{ status: 'fulfilled', value: 789 },
{ status: 'rejected', reason: 'reject' }
]*/
})
Promise.race()
race有竞赛的意思,表示多个Promise竞争,谁先有结果,就返回谁
cosnt p1 = Promise.resolve('resolve')
const p2 = Promise.reject('reject')
Promise.race([p1,p2]).then(res => {
console.log(res) // resolve
})
Promise.race([p2,p1])。catch(err => {
console.log(err) // reject
})
Promise.any()
Promise.any()是ES12中新增的方法,和race()方法类似
any()方法会等到一个fulfilled状态,来决定新Promise的状态,并返回第一个fulfilled状态的结果- 若所有的
Promise都是rejected,则返回一个AggregateError错误,可以在err.errors里面查看详情
const p1 = Promise.resolve(123)
const p2 = Promise.resolve(456)
const p3 = Promise.reject('reject1')
const p4 = Promise.reject('reject2')
Promise.any([p1,p2,p3,p4]).then(res => {
console.log(res) // 123
})
Promise.any([p3,p4,p1,p2]).then(res => {
console.log(res) // 123
})
Promise.any([p3,p4]).catch(err => {
console.log(err) // [AggregateError: All promises were rejected]
console.log(err.errors) // [ 'reject1', 'reject2' ]
})