async函数中未处理的拒绝会触发unhandledRejection事件,可能导致内存泄漏或进程终止;必须用try/catch捕获await、对非await Promise显式.catch(),并全局监听作兜底。

async 函数中未处理的拒绝(unhandled rejection)会导致 Node.js 发出 unhandledRejection 事件,长期忽略可能掩盖逻辑错误、引发内存泄漏,甚至在较新版本中直接终止进程(如 Node.js 15+ 默认行为)。关键不是“避免 reject”,而是确保每个 Promise 链最终被显式捕获或消费。
用 try/catch 包裹 await 表达式
这是最直接、最推荐的方式。async 函数内部的 await 会把 Promise 拒绝转换为同步异常,因此可用标准 try/catch 捕获:
- 所有可能失败的
await调用都应处于try块中 -
catch中需明确处理错误(记录日志、返回默认值、重新抛出等),不能空 catch - 避免在
catch中只写console.error(e)就结束——要决定后续流程是否继续、降级还是中断
不 await 的 Promise 必须显式 .catch()
如果出于性能或并发考虑,选择不 await 某个 Promise(例如发起多个并行请求但只关心第一个成功),必须手动附加 .catch() 防止它成为未处理拒绝:
- 错误写法:
fetch('/api/user').then(...)—— 若 fetch 失败且无.catch,即为 unhandled rejection - 正确写法:
fetch('/api/user').then(...).catch(err => console.warn('User fetch failed:', err)) - 更稳妥做法:对所有非 await 的 Promise 显式加
.catch(() => {})或转发到统一错误处理器
全局监听 unhandledRejection(仅作兜底和监控)
在应用入口(如 index.js)添加一次监听,用于日志记录和告警,**不可替代局部错误处理**:
- Node.js 中:
process.on('unhandledRejection', (reason, promise) => { console.error('Unhandled rejection at:', promise, 'reason:', reason); }) - 浏览器中:
window.addEventListener('unhandledrejection', event => { console.error('Unhandled rejection:', event.reason); }) - 监听器中不应静默吞掉错误;建议记录完整堆栈、上报监控系统,并在开发环境
throw reason加速问题暴露
避免常见陷阱
以下写法看似合理,实则容易遗漏拒绝处理:
-
不要在 async 函数中只写
someAsyncFn().catch(...)却不 await 它 —— 这仍是一个独立 Promise,其拒绝不会被外层 try/catch 捕获 - 不要依赖顶层 await(如模块级 await)来“自动捕获” —— 它没有对应的 try/catch 上下文,拒绝依然未处理
-
避免在循环中批量启动 Promise 却忘记统一收集和处理结果 —— 推荐用
Promise.allSettled()替代Promise.all(),它不会因单个失败而拒绝整个数组


















