漏掉 .catch() 不会立刻白屏,但会导致静默崩溃、监控失灵、堆栈截断、上下文丢失、内存泄漏等隐患;需分层兜底:入口 try/catch、链尾 .catch()、全局 unhandledrejection 监听,并禁用空 catch。

漏掉 .catch() 不会立刻让页面白屏,但会在后台埋下静默崩溃、监控失灵、用户体验断层等隐患。核心问题不是“程序崩了”,而是“错得无声无息”。
未捕获拒绝会触发 unhandledrejection,但控制台警告可能被忽略
浏览器遇到未处理的 Promise 拒绝时,会抛出 Uncaught (in promise) 警告,并触发 unhandledrejection 全局事件。问题在于:
- 开发者常只看控制台红字,而这类警告默认不中断执行,容易被滚动刷走
- 线上环境通常关闭 console 输出,警告彻底消失
- Node.js 15+ 默认会在未捕获拒绝时退出进程(非零退出码),导致服务闪退
错误上下文丢失,定位困难
Promise 链中一旦漏掉 .catch(),错误堆栈往往截断在异步边界:
-
fetch().then(res => res.json()).then(data => ...)中,若res.json()报解析错,堆栈里看不到原始请求 URL 和参数 - 错误 reason 可能是字符串或空对象,
err.stack为空,无法关联业务操作(如“用户点击提交按钮后失败”) - 多个并行请求中某一个失败,没有 catch 就无法区分是网络问题、后端异常还是前端逻辑错
内存泄漏风险被放大
未处理的拒绝本身不占内存,但它常伴随闭包引用滞留:
- Promise 回调里引用了组件实例、DOM 节点或大型缓存对象,拒绝后又没
.catch()消费 rejection reason,GC 无法回收整个作用域 - 轮询类逻辑(如
setInterval(() => api().catch(...)))若漏 catch,每次失败都积累一个未清理的 Promise,长期运行导致内存持续增长 - 全局变量意外保存了 reject 后的 Promise(如
window.pendingReq = fetch(...)),错误状态一直挂起,拖慢 GC
解决方案:分层兜底 + 显式责任归属
不靠一层 catch 走天下,而是按场景明确谁该捕获、怎么上报:
-
顶层 await 必须 try/catch:在事件处理器、生命周期钩子、路由守卫等入口处用
try { await api() } catch (e) { ... },这是业务错误的第一道防线 -
每个 Promise 链末尾加 .catch():哪怕只做日志,例如
fetch('/user').then(show).catch(logAndNotify) -
全局 unhandledrejection 监听作为最后保险:
window.addEventListener('unhandledrejection', e => { e.preventDefault(); reportError(e.reason, 'unhandled_promise'); }) -
禁用空 catch:写
.catch(() => {})等于主动丢错误;至少记录console.error或调用统一上报函数 -
关键链路补全 traceId 和业务标记:在 fetch 请求头加
X-Trace-ID,catch 时一并上传,方便后端日志串联


















