catch捕获其前所有未处理的拒绝状态,是then(null, handler)的语法糖,只捕获左侧错误且默认返回resolved Promise;若内部再抛错则继续向后传递。

在 Promise 链中,catch 会捕获它之前所有未被处理的拒绝(rejected)状态,包括 Promise 构造函数内部抛出的错误、reject() 调用,以及 then 回调中同步抛出的异常或返回的 rejected Promise。
catch 的作用范围是“链上最近的未捕获错误”
catch 实际上是 then(null, rejectionHandler) 的语法糖。它只捕获在其**前面**(左侧)尚未被处理的错误,不会影响后续 Promise 的执行流程:
- 如果
catch处理了错误,默认会返回一个 resolved 的 Promise(值为catch回调的返回值); - 如果
catch内部又抛错或返回 rejected Promise,错误会继续向后传递给下一个catch; - 没有
catch的链,最终错误会变成未处理的 rejection(触发unhandledrejection事件)。
常见写法与等效关系
以下三种写法行为一致:
promise.then(fn1).catch(handleError); promise.then(fn1).then(null, handleError); promise.then(fn1).then(undefined, handleError);
它们都捕获 promise 或 fn1 中发生的错误。注意:fn1 内异步操作(如另一个 Promise)抛出的错误,需在其内部处理,否则不会被外层 catch 捕获——除非你 return 它。
如何确保捕获所有可能错误?
关键原则:让每个可能出错的异步步骤都暴露为 Promise,并让错误沿链向下传递:
- 在
then回调中,不要用try/catch吞掉错误,除非你立刻return Promise.reject(e); - 避免在
then中直接 throw(虽然可行),更推荐return Promise.reject(new Error(...)); - 对嵌套 Promise,用
return把内层 Promise 返回出去,才能被外层catch接住; - 顶层链末尾加
.catch(console.error)是防御性好习惯。
一个典型例子
下面代码中,只有最后一个 catch 会执行:
Promise.resolve()
.then(() => { throw new Error('A'); })
.then(() => { console.log('never runs'); })
.catch(err => {
console.log('Caught:', err.message); // 输出 Caught: A
return 'recovered';
})
.then(val => {
console.log(val); // 输出 recovered
return Promise.reject(new Error('B'));
})
.catch(err => {
console.log('Also caught:', err.message); // 输出 Also caught: B
});
第一次 throw 被第一个 catch 捕获,链继续;第二次 reject 被第二个 catch 捕获。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











