async函数未捕获异常本质是Promise拒绝未被拦截,演变为未处理拒绝;需分层兜底:全局监听unhandledrejection、调用点try/catch、API层封装容错、并行用allSettled、工具函数to简化错误处理。

async 函数中未捕获的异常,本质是 Promise 被拒绝后没有被 await、.catch() 或 try/catch 拦截,最终演变为“未处理的 Promise 拒绝”。这类错误不会中断主线程,但容易静默丢失、影响调试,甚至在 Node.js 中导致进程退出。兜底策略不是替代主动处理,而是最后一道防线。
全局监听 unhandledrejection 事件
这是最通用的兜底手段,适用于浏览器和 Node.js(v15+),能捕获所有漏网的异步拒绝。
- 浏览器中使用
window.addEventListener('unhandledrejection', handler),建议在应用初始化早期注册 - Node.js 中用
process.on('unhandledRejection', (reason, promise) => {...});注意 v15+ 默认将未处理拒绝视为致命错误,必须显式监听否则进程会退出 - 事件对象包含
reason(拒绝值,可能是 Error、字符串或任意类型)和promise(被拒绝的 Promise 实例) - 适合做日志记录、监控上报(如 Sentry)、用户提示,但不要在此 throw 新错误或尝试恢复业务逻辑
按调用层级分层兜底
async 函数本身返回 Promise,内部 try/catch 只管自己,不保证调用方也处理了错误。因此需在关键调用点补上防御。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 事件处理器中调用 async 函数时,应链式加
.catch()或外层包try/catch,例如:button.addEventListener('click', async () => { try { await loadData(); } catch (e) { showNotification('加载失败'); } }); - React/Vue 等框架的生命周期钩子(如
mounted、useEffect)中启动 async 操作,同样需要显式错误处理,避免触发全局事件 - API 封装层可统一返回默认值或空对象,而不是让错误直接冒泡到 UI 层
并行操作优先用 Promise.allSettled
多个无依赖的异步任务(如同时拉取用户、权限、配置)若用串行 await,一个失败就会中断后续;若只靠 Promise.all,一个失败则全盘拒绝——这都会增加兜底负担。
立即学习“Java免费学习笔记(深入)”;
-
Promise.allSettled返回每个任务的完整结果({ status: 'fulfilled' | 'rejected', value | reason }),天然容错 - 后续可遍历结果,对失败项单独打日志、降级处理或聚合上报,不干扰成功项的流程
- 比在每个
await后手动.catch()更简洁,也比全局兜底更精准
封装安全 await 工具函数
把“错误即值”模式落地,让异步调用像同步一样可预测,减少 try/catch 噪声。
- 实现类似
const [err, data] = await to(fetch('/api/user'));的辅助函数,内部自动包裹 try/catch - 适用于简单场景(如单个请求需 fallback),避免为每个 await 写重复结构
- 注意:不能替代业务层的错误分类(如区分 401 和网络超时),仍需在拿到
err后做语义判断

















