JS异步错误导致崩溃的本质是未捕获、未响应、未降级;防范需建立分层机制:顶层await配try/catch、Promise链末尾强制.catch()、全局监听unhandledrejection并上报。

JS 中异步错误处理不当导致页面崩溃,本质是错误未被捕获、未被响应、也未被降级,最终中断主线程或触发全局异常终止。防范的关键不是堵住所有错误,而是建立分层响应机制,让错误“浮上来、看得见、可恢复”。
顶层 await 必须配 try/catch
async 函数内部的 await 不会自动把 Promise 拒绝转为同步异常;不加 try/catch,错误就直接变成 unhandled rejection,可能在部分环境(如严格模式)中导致脚本终止。
- 按钮点击、组件挂载、路由进入等用户触发的顶层异步调用,必须用 try/catch 包裹
- 避免只在内部函数里 catch 后 throw,而调用方不处理——错误仍在边界处丢失
- 每个 await 表达式都应明确失败策略:重试?展示缓存?跳转错误页?不能默认“不管”
Promise 链末尾强制 .catch()
Promise 一旦 reject 且链上无 .catch() 或 .then(null, handler),就会成为未处理拒绝,不仅控制台报错,还可能影响后续任务执行。
- fetch().then(res => res.json()).then(data => render(data)) 必须接 .catch(),否则 JSON 解析失败即静默
- 避免写成 fetch().then(...).then(...) 后漏掉 .catch(),中间任意环节抛错都无法拦截
- 即使只是记录日志,也要写 .catch(err => console.error('API 调用异常:', err))
全局兜底:监听 unhandledrejection
再严谨的局部处理也会遗漏,unhandledrejection 是捕获漏网 Promise 错误的最后防线。
- 在应用初始化时注册:window.addEventListener('unhandledrejection', event => { event.preventDefault(); reportError(event.reason); })
- 注意:event.preventDefault() 只屏蔽控制台警告,不影响你自行上报,生产环境不应省略上报逻辑
- 搭配 traceId 和当前页面、操作上下文一并上报,便于快速定位问题源头
避开静默失败的典型陷阱
有些写法看似无害,实则让错误彻底消失,排查时毫无痕迹。
- 不要在 forEach(async () => {}) 中使用 await —— 循环不会等待,错误无法被外层捕获
- setTimeout(() => { throw new Error('xxx') }) 不属于 Promise,不会触发 unhandledrejection,需靠 window.onerror 捕获
- 禁止空 catch:至少 console.error(err) 或调用统一上报函数,否则等于主动吞错


















