async函数未捕获的错误会触发unhandledrejection事件,浏览器中用window.addeventlistener监听,node.js需用process.on;应结合try/catch、.catch()兜底和eslint等工具预防。

async 函数内部抛出的错误(或 Promise.reject)如果未被 try/catch 或 .catch() 捕获,会变成 **未处理的 rejection(unhandled rejection)**,默认不会中断主线程,但会触发 unhandledrejection 事件 —— 这是捕获“async 函数外部未捕获 reject”的关键入口。
监听 unhandledrejection 事件
这是最直接、全局性捕获所有未被处理的 Promise reject 的方式。它在 rejection 发生且没有被任何 .catch() 或 await 后的 try/catch 拦截时触发:
window.addEventListener('unhandledrejection', (event) => {
console.error('全局未捕获的 Promise reject:', event.reason);
// 可上报错误、记录日志、提示用户等
event.preventDefault(); // 阻止默认控制台警告(可选,不推荐屏蔽)
});
注意:
- event.reason 就是被 reject 的值(可能是 Error 实例,也可能是字符串、数字等);
- 该事件仅在浏览器环境有效;Node.js 中需监听 process.on('unhandledRejection');
- event.preventDefault() 可阻止浏览器在控制台打印黄色警告,但建议保留日志以便调试,而非静默忽略。
确保 async 函数调用链有兜底处理
很多“外部未捕获”问题其实源于调用方疏忽。例如:
async function fetchData() {
throw new Error('API failed');
}
<p>// ❌ 危险:没 catch,也没 await(或没 .catch)
fetchData();</p><p>// ✅ 正确:显式处理
fetchData().catch(err => console.error(err));</p><p>// ✅ 或在顶层 async IIFE 中 try/catch
(async () => {
try {
await fetchData();
} catch (err) {
console.error(err);
}
})();</p>
常见易漏场景:
- 事件处理器中直接调用 async 函数但未处理返回的 Promise;
- React/Vue 等框架中,在 useEffect / mounted 等钩子中启动 async 操作却忘记 .catch();
- 调用第三方库的 async 方法,误以为“不 await 就没事”,实则丢弃了 rejection。
使用工具辅助检测潜在遗漏
靠人工检查容易遗漏,可借助以下手段提前发现:
-
ESLint 规则:启用
require-await+no-floating-promises(TypeScript)或promise/no-floating-promises(eslint-plugin-promise),能识别未处理的 Promise 表达式; - 测试覆盖率 + 模拟 reject:单元测试中强制让异步函数 reject,并验证是否有对应错误处理逻辑;
-
监控平台集成:将
unhandledrejection事件上报至 Sentry、Bugsnag 等,形成生产环境兜底告警。
Node.js 环境注意事项
Node.js 不支持 unhandledrejection 全局事件监听(需用 process):
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
// 记录日志、发送告警、或 process.exit(1)(谨慎!)
});
⚠️ 注意:Node.js v15+ 默认会在未处理 rejection 时触发 process.exit(1)(除非监听了该事件),所以线上服务务必监听并至少记录,避免进程意外退出。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











