避免 async 函数中出现未捕获异常的核心是不让 promise 拒绝漏网,需在每一层调用链主动设防:每个 await 配 try/catch、调用点必须处理返回的 promise、并行任务优先用 allsettled、全局监听 unhandledrejection 作为最后兜底。

避免 async 函数中出现未捕获的异常,核心在于不让 Promise 拒绝“漏网”——异常必须被显式拦截或兜底捕获。关键不是等错误发生再补救,而是从调用链每一层主动设防。
每一处 await 都要配 try/catch
async 函数内部的 await 表达式一旦失败,就会让整个函数返回一个 rejected Promise。如果不加 try/catch,这个拒绝就直接向上抛出,极易脱离控制。
- 对单个高风险操作(如 fetch、数据库查询)单独包裹 try/catch,便于针对性降级或重试
- 避免在同一个 try 块里 await 多个无关任务——一个失败会中断后续,必要时改用 allSettled
- catch 中不要静默吞掉错误:至少记录日志,再根据业务决定是 re-throw、返回默认值,还是跳转提示页
调用点必须处理返回的 Promise
async 函数本身不抛同步异常,它只返回 Promise。调用方若不 await 或不 .catch(),错误就彻底丢失。
- 事件监听器中调用 async 函数,务必用 async 匿名函数 + try/catch,或链式 .catch()
- 框架生命周期钩子(如 Vue 的 onMounted、React 的 useEffect)里启动异步逻辑,同样需要外层防护
- Express 等服务端路由中,推荐用高阶包装器(如 asyncHandler),把 Promise 错误统一交给 next() 处理
并行任务优先用 allSettled
多个独立异步操作同时进行时,Promise.all 会因任一失败而全盘拒绝,导致部分成功结果也被丢弃;而逐个 await 又牺牲并发性。
- allSettled 返回数组,每个元素含 status 和 value/reason,可分别判断成败
- 适合批量请求(如拉取用户信息、权限列表、配置项),失败项可单独打日志或提供默认值,不影响整体流程
- 比在每个 await 后写 .catch() 更简洁,也比依赖全局监听更精准可控
加一道全局兜底防线
即使层层设防,仍可能有遗漏。unhandledrejection 是最后一道安全网,尤其在生产环境不可或缺。
- 浏览器中尽早注册 window.addEventListener('unhandledrejection', ...)
- Node.js v15+ 必须监听 process.on('unhandledRejection', ...),否则进程会直接退出
- 该事件只捕获真正未处理的拒绝,适合做错误上报、监控告警,但不能替代主动捕获——它拿不到完整调用栈,也无法恢复业务状态










