Promise详解
Promise
解决回调地狱问题
当我们new
一个promise
,此时我们需要传递一个回调函数,这个函数为立即执行的,称之为(executor)
这个回调函数,我们需要传入两个参数回调函数,reslove
,reject
(函数可以进行传参)
- 当执行了
reslove
函数,会回调promise对象的.then函数 - 当执行了
reject
函数,会回调promise对象的.catche函数
Executor立即执行
1 |
|
Promise状态
使用promise
的时候,给它一个承诺,我们可以将他划分为三个阶段
- pending(待定),执行了executor,状态还在等待中,没有被兑现,也没有被拒绝
- fulfilled(已兑现),执行了
resolve
函数则代表了已兑现状态 - rejected(已拒绝),执行了
reject
函数则代表了已拒绝状态
首先,状态只要从待定状态,变为其他状态,则状态不能再改变
1 |
|
- 当我调用
reject
之后,在调用resolve
是无效的,因为状态已经发生改变,并且是不可逆的。
resolve不同值的区别
如果
resolve
传入一个普通的值或者对象,只能传递接受一个参数,那么这个值会作为then
回调的参数1
2
3
4
5
6new Promise((resolve, reject) => {
resolve({name: '张三', age: 5})
}).then(res => {
console.log(res);
})
// {name: '张三', age: 5}如果
resolve
中传入的是另外一个Promise
,那么这个新Promise
会决定原Promise
的状态1
2
3
4
5
6
7
8
9
10
11
12const promise = new Promise((resolve, reject) => {
resolve(new Promise((resolve, reject) => {
setTimeout(() => {
reject('执行失败')
}, 3000);
}))
})
promise.then(res => console.log(res))
.catch(err => console.log(err))
// 打印内容: 执行失败上述例子虽然执行的是resolve,但是会触发传入的Promise的reject,从而执行catch方法。所以新传入的Promise会决定原来的Promise状态;
如果
resolve
中传入的是一个对象,并且这个对象有实现then
方法,那么会执行该then
方法,then
方法会传入resolve
,reject
函数。此时的promise
状态取决于你调用了resolve
,还是reject
函数。这种模式也称之为: thenable1
2
3
4
5
6
7
8
9
10
11
12const promise = new Promise((resolve, reject) => {
resolve({
then(res, rej) {
rej("失败")
}
})
})
promise.then(res => console.log(res))
.catch(err => console.log(err))
// 输出内容:失败
Promise的实例方法
实例方法,存放在
Promise.prototype
上的方法,也就是Promise的显示原型上,当我new Promise的时候,会把返回的改对象的 promise[[prototype]](隐式原型) === Promise.prototype (显示原型)即new返回的对象的隐式原型指向了Promise的显示原型
then方法
then
方法可以接受参数,一个参数为成功的回调,另一个参数为失败的回调1
2
3
4
5
6
7
8const promise = new Promise((resolve, reject) => {
// resolve('request success')
reject('request error')
})
promise.then(res => console.log(res), rej => console.log(rej))
// 输出内容:request error如果只捕获错误,还可以这样写
- 因为第二个参数是捕获异常的,第一个可以写个
null
或""
占位
1
2
3
4
5
6
7
8const promise = new Promise((resolve, reject) => {
// resolve('request success')
reject('request error')
})
promise.then(null, rej => console.log(rej))
// 输出内容:request error- 因为第二个参数是捕获异常的,第一个可以写个
then
方法是有返回值的,它的返回值是
promise1
2
3
4
5
6const promise = new Promise((resolve, reject) => {
resolve('执行成功')
})
console.log(promise.then(res => ({name:'张三', age:22})))
// 返回的是一个Promise对象返回一个普通值 状态:fulfilled
1
2
3
4
5
6
7const promise = new Promise((resolve, reject) => {
resolve('执行成功')
})
promise.then(res => ({name:'张三', age:22}))
.then(res => console.log(res))
// {name: '张三', age: 22}返回一个普通值,则相当于主动调用
Promise.resolve
,并且把返回值作为实参传递到then
方法中。如果没有返回值,则相当于返回
undefined
1
2
3
4
5
6
7
8const promise = new Promise((resolve, reject) => {
resolve('执行成功')
})
promise.then(res => (console.log(111)))
.then(res => console.log(res))
// 111
// undefined
明确返回一个promise状态:fulfilled
1
2
3
4
5
6
7
8
9
10const promise = new Promise((resolve, reject) => {
resolve('执行成功')
})
promise.then(res => {
return new Promise((resolve, reject) => {
resolve('返回的Promise对象resolve里面的内容')
})
}).then(res => console.log(res))
// 返回的Promise对象resolve里面的内容返回一个thenable对象 状态:fulfilled
1
2
3
4
5
6
7
8
9
10
11
12
13const promise = new Promise((resolve, reject) => {
resolve('hi ice')
})
promise.then(res => {
return {
then(resolve, reject) {
resolve('hi webice')
}
}
}).then(res => console.log(res))
//hi webice
catch方法
如果返回值明确一个promise或者thenable对象,取决于你调用了
resolve
还是reject
返回一个普通对象
1
2
3
4
5
6
7const promise = new Promise((resolve, reject) => {
reject('失败')
})
promise.catch(err => ({name:'张三', age: 22}))
.then(res => console.log(res)) // 如果这里调用.catch,什么也不会输出
// {name:'张三', age: 22}明确返回一个promise
1
2
3
4
5
6
7
8
9
10
11const promise = new Promise((resolve, reject) => {
reject('ice error')
})
promise.catch(err => {
return new Promise((resolve, reject) => {
reject('ice error promise')
})
}).catch(res => console.log(res))
//ice error promise返回thenable对象
1
2
3
4
5
6
7
8
9
10
11
12
13const promise = new Promise((resolve, reject) => {
reject('ice error')
})
promise.catch(err => {
return {
then(resolve, reject) {
reject('ice error then')
}
}
}).catch(res => console.log(res))
//ice error then
finally方法
- finally(最后),无论promise状态是fulfilled还是rejected都会执行一次
finally
方法
Promise中的类方法/静态方法
Promise.reslove/Promise.reject
有的时候,你已经预知了状态的结果为fulfilled,则可以用这种简写方式
1
2
3Promise.resolve('abc')
//等价于
new Promise((resolve, reject) => resolve('abc'))有的时候,你已经预知了状态的结果为rejected,则可以用这种简写方式
1
2
3Promise.reject('error')
//等价于
new Promise((resolve, reject) => reject('error'))
Promise.all
fulfilled 状态
1 |
|
- all方法的参数传入为一个可迭代对象,返回一个promise,只有三个都为
resolve
状态的时候才会调用.then
方法。 - 只要有一个promise的状态为rejected,则会回调
.catch
方法
rejected状态
1 |
|
- 当遇到rejectd的时候,后续的promise结果我们是获取不到,并且会把reject的实参,传递给catch的err形参中
上面的
Promise.all
有一个缺陷,就是当遇到一个rejected的状态,那么对于后面是resolve
或者reject
的结果我们是拿不到的
- ES11 新增语法
Promise.allSettled
,无论状态是fulfilled/rejected都会把参数返回给我们
Promise.allSettled
1 |
|
- 该方法会在所有的Promise都有结果,无论是fulfilled,还是rejected,才会有最终的结果
其中一个promise没有结果
1 |
|
Promise.race
- race(竞争竞赛)
- 优先获取第一个返回的结果,无论结果是fulfilled还是rejectd
1 |
|
Promise.any
- 与race类似,只获取第一个状态为fulfilled,如果全部为rejected则报错
AggregateError
1 |
|
async/await
Promise的语法糖,可以增加代码的可读性(用同步的思维写代码)
await后面的代码都是异步的
- async(异步的)
- async 用于申明一个异步函数
async内部代码同步执行
- 异步函数的内部代码执行过程和普通的函数是一致的,默认情况下也是会被同步执行
异步函数的返回值
普通函数主动返回什么就返回什么,不返回为
undefined
异步函数的返回值特点
- 明确有返回一个普通值,相当于
Promise.resolve
(返回值) - 返回一个thenable对象则由,then方法中的
resolve
,或者reject
有关 - 明确返回一个promise,则由这个promise决定
- 明确有返回一个普通值,相当于
异步函数的异常处理
- 如果函数内部中途发生错误,可以通过try catch的方式捕获异常
- 如果函数内部中途发生错误,也可以通过函数的返回值.catch进行捕获
1 |
|
await 关键字
- 异步函数中可以使用
await
关键字,普通函数不行 - await特点
- 通常await关键字后面都是跟一个Promise
- 可以是普通值
- 可以是thenable
- 可以是Promise主动调用
resolve或者reject
- 这个promise状态变为fulfilled才会执行
await
后续的代码,所以await
后面的代码,相当于包括在.then
方法的回调中,如果状态变为rejected,你则需要在函数内部try catch
,或者进行链式调用进行.catch
操作
- 通常await关键字后面都是跟一个Promise
手写Promise加载图片
1 |
|
参考文章
https://juejin.cn/post/7144308012952322084
Promise阅读代码题:https://juejin.cn/post/6844904077537574919