Promise.prototype.catch 捕获最近未处理的 rejected,统一捕获需确保错误向下传递不中断链:中间.catch()须返回Promise.resolve()或重抛错误,末尾.catch()兜底所有上游异常。

Promise.prototype.catch 能捕获当前 Promise 链中**最近的、未被处理的拒绝态(rejected)**,但要真正“统一捕获”整个异步链条的异常,关键在于**确保错误始终向下传递,不被中间的 .catch() 意外吞掉,且链式调用保持连续**。
确保 Promise 链不断裂
一旦某个 .then() 或 .catch() 中抛出错误,又没被后续的 .catch() 捕获,就会变成未处理的 rejection。统一捕获的前提是让所有可能的错误都流到链尾:
- 避免在中间
.then()中用try/catch吞掉同步错误而不 re-throw —— 这会让 Promise 变成 rejected,但若后面没.catch()就丢失了 - 中间的
.catch()如果只是做日志或降级处理,**必须返回一个新 Promise(如Promise.resolve()或继续 throw)**,否则默认返回undefined,导致后续.then()接收到undefined,链仍在,但错误已消失 - 示例:
fetch('/api/data')
.then(res => {
if (!res.ok) throw new Error('HTTP error');
return res.json();
})
.catch(err => {
// ✅ 正确:处理后继续传递错误(或返回 Promise.reject)
console.warn('请求失败,尝试缓存', err);
return getCachedData().catch(() => Promise.reject(err)); // 失败则把原错误再抛出
})
.then(data => processData(data))
.catch(err => console.error('全局兜底错误:', err)); // 所有路径最终到这里
用 .catch() 放在链尾作为“兜底处理器”
这是最常用也最有效的统一捕获方式。只要 Promise 链没有提前终止,所有上游未被捕获的 rejection 都会冒泡到这个末尾 .catch():
- 它能捕获:
–fetch失败
–.then()中throw的错误
–.then()返回的 Promise 被 reject
– 前一个.catch()中再次 throw 的错误 - 注意:如果链中有多个
.catch(),只有**最后一个未被更下游.catch()捕获的 rejection** 才会到达这里;所以通常只在链末端放一个,中间只做局部处理并主动传递
配合 async/await 时的等效写法
使用 async/await 时,统一捕获靠 try/catch,但逻辑一致:
立即学习“Java免费学习笔记(深入)”;
-
try块内所有 await 表达式产生的 rejection 都会被同一个catch捕获 - 若在
catch中做了部分处理(如重试),仍需明确throw或return Promise.reject()才能让外层继续捕获 - 示例:
async function loadData() {
try {
const res = await fetch('/api/data');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return await res.json();
} catch (err) {
console.error('加载失败:', err);
throw err; // ✅ 主动重抛,保证调用方能统一处理
}
}
loadData().catch(err => console.error('最终错误:', err));
补充:全局未捕获 rejection 监听(仅作兜底,不可替代链式 catch)
可监听 unhandledrejection 事件捕获漏网之鱼,但这是最后防线,不能用于业务逻辑控制:
window.addEventListener('unhandledrejection', event => { console.error('未捕获的 Promise 错误:', event.reason); });- 它不改变执行流,也无法恢复或重试,仅适合日志上报
- 依赖此机制说明链式错误处理设计有问题,应优先优化 Promise 链结构


















