最直接有效的方式是在每个 promise 链末尾明确加 .catch() 并配合全局 unhandledrejection 监听兜底;fetch 和 json 解析需合并校验与解析再统一捕获;async/await 中未 await 的 promise 仍需显式 .catch()。

最直接有效的方式,就是在每个 Promise 链末尾明确加上 .catch(),同时配合全局 unhandledrejection 监听作为兜底。漏掉末尾捕获是异步错误静默消失的主因,不是代码写得不够多,而是结构上缺少收口。
链末统一加 .catch() 是硬性规范
无论 Promise 链多短、看起来多“安全”,只要没接 .catch(),任何环节出错(HTTP 失败、res.json() 解析异常、then 回调里 throw、甚至返回一个被 reject 的新 Promise)都会被吞掉。
- 正确写法:所有链必须以
.catch()收尾,哪怕只是转发给集中错误处理器 - 避免中间加
.catch()后直接接.then()——这会让后续步骤的错误逃逸 - 不要依赖
try/catch包裹 Promise 链调用,它对异步 reject 无效
fetch 和 JSON 解析是高频漏点
fetch 默认不校验 HTTP 状态码,res.json() 在非 JSON 响应时会直接 reject,这两步合起来极易漏处理。
- 别写
fetch(...).then(res => res.json())—— 这里没 catch,网络成功但响应体非法就静默失败 - 推荐把状态校验和解析合并进第一个
then,再统一.catch() - 示例:
fetch('/api').then(r => r.ok ? r.json() : Promise.reject(new Error(r.status))).catch(handleError)
全局 unhandledrejection 是最后防线
即使团队严格执行链末 .catch(),人总会疏忽。注册 unhandledrejection 能捕获所有漏网的 rejected Promise,是生产环境必备兜底。
- 浏览器中:
window.addEventListener('unhandledrejection', e => { e.preventDefault(); reportError(e.reason); }) - Node.js 中:
process.on('unhandledRejection', (reason, promise) => { reportError(reason); }) - 注意:它不能替代链末
.catch(),而是补位;不调用preventDefault()时控制台仍会警告
async/await 场景别混淆语法层级
用 async/await 时,错误捕获靠 try/catch,但它只管当前函数体内 await 的 Promise。如果在 try 块外还调用了其他 Promise 链,那些链仍需自己收尾。
- 错误示范:
async function f() { const p = apiCall(); try { await p } catch(e) {} }——p没.catch(),一旦拒绝仍会触发 unhandledrejection - 正确做法:要么
await它,要么显式.catch(),不能放任不管 - 尤其注意事件回调、定时器内启动的 Promise,它们脱离主流程,更易遗漏
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











