promise链中错误捕获的核心是.catch()的链式传播机制,它能捕获上游所有未处理的拒绝,包括前一个promise的reject、then中同步throw及返回的被拒promise;.then()第二参数仅处理当前promise拒绝;末尾统一.catch()最稳妥;async/await中可用try/catch替代。

在 Promise 链中捕获前一个 Promise 的错误,核心是利用 .catch() 的链式传播机制——它会捕获其**上游所有未被处理的拒绝(rejection)**,包括前一个 Promise 的 reject、then 回调里同步 throw 的错误,以及 then 中返回的被拒 Promise。
catch 作用于整个上游链
.catch() 不只管紧挨着的前一个 Promise,而是“向后看”整条链中从它开始往前所有没被拦截的错误。只要错误没被前面的 .catch() 或 .then() 的第二个参数处理过,就会一直传到它这里。
- 例如:
promiseA().then(() => promiseB()).then(() => { throw new Error('boom') }).catch(...)—— 这里的 catch 能捕获 promiseA 拒绝、promiseB 拒绝,以及最后那个同步 throw - 但如果写成:
promiseA().catch(() => {}).then(() => promiseB()).catch(...),那么第一个 catch 已经“吞掉”了 promiseA 的错误,第二个 catch 就只管 promiseB 及之后的错误
用 .then() 的第二个参数捕获当前层错误
在 .then(onFulfilled, onRejected) 中传入第二个函数,可以专门处理**当前 Promise 实例本身的拒绝**,但不会接收后续 then 中抛出的错误。
- 适合做“局部兜底”,比如请求失败时返回默认值:
fetch('/api').then(res => res.json(), () => ({ id: 0, name: 'offline' })) - 注意:这个 onRejected 只对 fetch 这个 Promise 生效;如果 res.json() 报错,它捕获不到,得靠后面的 catch
避免错误“漏网”的关键位置
把 .catch() 放在链的**末尾**是最稳妥的做法,相当于给整条链加统一错误出口:
- 推荐写法:
apiCall().then(parse).then(render).catch(handleError) - 不推荐只在中间加 catch 后就不管了,比如
apiCall().catch(log).then(...)—— 后续环节出错仍会触发 unhandledrejection 警告 - 如果需要分层处理(如网络层错误 vs 业务层错误),可用多个 catch:
.catch(networkErr => {...}).then(...).catch(bizErr => {...})
async/await 下更直观的替代方案
如果你用 async/await,可以直接配合 try/catch 捕获前一个 await 表达式的错误,语义更清晰:
try { const data = await apiCall(); await parse(data); await render(data); } catch (err) { handleError(err); }- 每个 await 相当于链中的一个 Promise 节点,try/catch 自动覆盖其上游最近的异步拒绝
- 注意:try/catch 对纯 Promise 构造器内的同步 throw 无效,必须是 await 触发的 Promise 状态变更











