async函数中未处理的Promise错误会触发unhandledrejection事件;应全局监听该事件兜底,避免“发射即忘”,对每个await用try/catch包裹,并借助ESLint和TypeScript静态检查预警。

async 函数中抛出的错误,只有在被 await 或调用方显式处理时才会被捕获;如果一个 promise 被创建但从未被 await、.then() 或 .catch() 关联,它就成了“未被等待的 promise”——这类 promise 若 reject,会触发全局 unhandledrejection 事件,但不会中断当前执行流,也容易被忽略。
监听 unhandledrejection 事件(基础兜底)
这是捕获所有未被处理 rejection 的最直接方式,适用于开发和测试阶段快速发现问题:
建议在应用初始化时全局注册一次:
window.addEventListener('unhandledrejection', (event) => {
console.error('Unhandled Promise Rejection:', event.reason);
// 可上报监控系统、记录日志、或开发环境弹窗提醒
event.preventDefault(); // 阻止默认控制台警告(可选)
});
注意:Node.js 环境用 process.on('unhandledRejection', ...),且该事件仅对真正“无人监听”的 rejection 触发(比如没 .catch()、没 await、也没被 try/catch 包裹)。
立即学习“Java免费学习笔记(深入)”;
避免在 async 函数中“发射即忘”Promise
常见陷阱是调用一个 async 函数却不 await 它,导致其内部错误无法冒泡到上层:
- ❌ 错误写法:
saveLog(data); // 忘了 await → 错误静默丢失 - ✅ 正确写法:
await saveLog(data);或saveLog(data).catch(console.error); - ✅ 若确实不需要等待结果(如埋点、日志),务必显式处理 rejection:
saveLog(data).catch(err => console.debug('Log failed, ignored:', err));
用 try/catch 包裹 await 表达式(主动防御)
async 函数内每个 await 都应处于 try/catch 中,否则 rejection 会直接抛出到函数外部,若外部也未处理,就变成未捕获错误:
async function fetchData() {
try {
const res = await fetch('/api/data');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return await res.json();
} catch (err) {
console.error('Fetch failed:', err);
throw err; // 或返回默认值、重试、降级等
}
}
注意:try/catch 只捕获当前 await 的 rejection,不能跨多个独立 await 自动串联;每个可能失败的 await 最好单独包裹或统一处理。
工具辅助:ESLint + TypeScript 提前预警
借助静态检查减少疏漏:
- ESLint 插件
eslint-plugin-promise提供promise/no-floating-promises规则,可检测未被 await/.then/.catch 处理的 promise 表达式 - TypeScript 4.4+ 在启用
"noImplicitReturns": true和严格模式下,配合类型推导也能提示某些遗漏 await 的路径 - 编辑器实时提示 + CI 中集成 ESLint,能有效拦截多数“发射即忘”场景



















