async/await 的异常边界是 await 表达式所在 async 函数的作用域,错误仅在该函数内被 try/catch 捕获,否则以 rejected promise 向上抛出直至被外层处理或触发 unhandledrejection。

async/await 的异常边界,本质是“await 表达式所在函数的作用域”——错误只会在该 async 函数内部被 try/catch 捕获;若未捕获,就会以拒绝态 Promise 向上抛出,直到被外层调用处的 .catch() 或更外层的 try/catch 接住,否则触发 unhandledrejection。
明确异常传播的起点和终点
await 不是“吞掉错误”的开关,而是把 Promise rejection 同步化抛出:它让被 await 的 Promise 一旦 reject,就立刻在当前行表现为一个可被 try/catch 捕获的错误。但这个机制只对当前 await 有效,不自动延伸到函数返回值或调用链之外。
- 如果在 async 函数里 await 一个 reject 的 Promise,且没写 try/catch → 函数立即返回 rejected Promise
- 如果调用方用
fn().catch(...)→ 能捕获这个 rejected Promise - 如果调用方只写
await fn()却没包 try/catch → 错误继续上抛,可能落到全局 unhandledrejection -
return Promise.reject(...)不会触发当前函数内的 catch(因为没 await),等同于直接返回失败 Promise
避免异常“漏出”边界的三个关键动作
边界模糊常导致错误静默失败或崩溃。守住它要靠主动设计:
- 每个顶层 async 入口必须有兜底处理:比如页面初始化函数、事件处理器、API 调用封装,都应自带 try/catch 或 .catch()
-
并行任务慎用统一 try/catch:若用
await Promise.all([p1, p2]),任一失败即中断全部;想各自独立容错,应先用.catch()给每个 Promise 设置默认值,再 await all -
显式监听未捕获异常:在应用启动时注册
window.addEventListener('unhandledrejection', handler),至少记录日志,防止错误彻底丢失
常见边界误判场景
这些写法看似合理,实则让异常逃逸:
-
async function load() { return fetch('/api').then(r => r.json()); }—— fetch 失败时,.then 内部不会 throw,而是返回 rejected Promise,但 load 函数没 await 它,错误无法被 load 内部的 try/catch 捕获 -
async function init() { doSomething(); await step1(); await step2(); }—— doSomething() 若是异步但没 await,它的错误完全游离在当前 try/catch 之外 -
button.onclick = async () => { await apiCall(); };—— 点击后出错,既没 catch 也没监听,直接变成 unhandledrejection
异常边界不是语言强制划定的线,而是你用 await、try/catch 和 Promise 链共同画出来的责任区。守住了,错误才可控;模糊了,问题就难定位。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











