async函数中try/catch仅捕获同步错误和await等待的promise被reject时的错误,未await的promise错误会变为unhandled rejection;多个await串行时首个reject即触发catch,promise.all则捕获首个失败原因;.catch()可吞掉错误阻止外层try/catch触发。

async 函数内部的异步错误捕捉,核心在于错误是否发生在 Promise 链中,以及你用的是 try/catch 还是 .catch()。它不看“谁先写”,而看“错误实际在哪一环被抛出和传递”。
try/catch 只捕获同步代码和 await 后立即 reject 的 Promise
try/catch 在 async 函数里能捕获两类错误:
- 同步抛出的错误(比如
throw new Error('sync')) - 被
await等待的 Promise 被 reject —— 此时await会把 reject 转为抛出异常,try/catch就能接住
注意:await promise 等价于 promise.then(v => v).catch(e => { throw e }),所以它本质是把 Promise rejection “转译”成 throw。
未 await 的 Promise 错误会掉出 try/catch,变成 unhandled rejection
如果你启动了一个 Promise 但没 await 它,它的 rejection 就不会触发 try/catch:
async function fn() {
try {
Promise.reject('oops'); // ❌ 不会被 catch 到
// 没 await,这个 Promise 自己跑,错误没人管
} catch (e) {
console.log('never reached');
}
}
fn(); // 触发 UnhandledPromiseRejectionWarning
这种错误只能靠全局监听(process.on('unhandledRejection') 或 window.addEventListener('unhandledrejection'))兜底,不能靠函数内 try/catch 捕获。
多个 await 并行时,错误优先级由第一个 reject 决定
当多个 await 串行执行,第一个 reject 的 Promise 会让 try/catch 立即退出,后续 await 不再执行:
async function fn() {
try {
await Promise.reject('first'); // ✅ 这个错误被捕获
await Promise.resolve('second'); // ❌ 不会执行
} catch (e) {
console.log(e); // 'first'
}
}
如果是并行 Promise(如 await Promise.all([p1, p2])),则只要其中一个 reject,Promise.all 就 reject,await 把它转为 throw,try/catch 捕获到的就是那个最先 reject 的错误(严格说,是 Promise.all 决议失败时传入的 reason)。
显式 .catch() 和 try/catch 可共存,但作用域不同
.catch() 是 Promise 链自身的错误处理,它不会影响外层 try/catch:
async function fn() {
try {
await Promise.reject('outer')
.catch(e => console.log('inner:', e)); // ✅ 捕获并吞掉
} catch (e) {
console.log('outer:', e); // ❌ 不会执行
}
}
这里 .catch() 吞掉了 rejection,Promise 变成了 resolved 状态,所以 await 不会 throw,try/catch 也就无事发生。反过来,如果 .catch() 里又 throw,那外层 try/catch 就能捕获。
不复杂但容易忽略:async 函数里的错误流,本质是 Promise 链 + await 语法糖的组合行为。关键不是“写在哪”,而是“错误有没有被 await 接住”、“有没有在链上被处理掉”。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











