在真实开发环境的情况下,有可能遇到一种情况就是,Promise链式处理数据,中间部分发现有数据错误,这时候就需要中断Promise链。
分析
一开始的想法是把执行函数中的reject
包裹进数据中传递下去,例如:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16new Promise(function(resolve, reject) {
resolve(reject)
}).then((reject) => {
console.log(1)
return reject
})
.then((reject) => {
console.log(2)
return reject
})
.then(() => {
console.log(3)
reject()
})
.then(() => console.log(4))
.catch((err) => console.log(err))
结果是失败的,依然会执行输出后面的4
。
原因是,因为在执行resove
以后,该Promise的状态已经改变为Fulfilled
状态,Promise状态的转换只能从Pending -> FulFilled
或 Pending -> Rejected
解决方案
1. 使用变量确定是否执行
设定一个Promise作用域以外的变量,来确定then
中操作是否执行:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20let continueRun = true
function thenTask(func) {
if (continueRun) {
func()
}
}
Promise.resolve()
.then(() => thenTask(() => {
console.log(1)
}))
.then(() => thenTask(() => {
console.log(2)
}))
.then(() => thenTask(() => {
console.log(3)
continueRun = false
}))
.then(() => thenTask(() => {
console.log(4)
}))
2. 调用Promise.reject
虽然当前Promise已经不能再转为rejected
状态,但是可以通过返回一个新的Promise对象调用reject()
方法来中断当前的Promise链1
2
3
4
5
6
7
8
9Promise.resolve()
.then(() => console.log(1))
.then(() => console.log(2))
.then(() => {
console.log(3)
return Promise.reject()
})
.then(() => console.log(4))
.catch((err) => console.log(err))
因为reject的本质其实就是抛出异常让catch捕获,因此Promise.reject
抛出异常后就会中断当前执行中的任务链。需要注意的是,catch是会捕捉到return Promise.reject()
的异常的,所以需要在catch中区分开中断的操作和其他异常。
3.抛出异常
跟方法2一样,直接抛出异常中断流程。1
2
3
4
5
6
7
8
9Promise.resolve()
.then(() => console.log(1))
.then(() => console.log(2))
.then(() => {
console.log(3)
throw new Error('break')
})
.then(() => console.log(4))
.catch((err) => console.log(err))