async/await 使异步错误可被 try/catch 捕获,前提是调用时使用 await;否则错误变为未处理的 promise rejection,finally 会同步执行而漏掉错误,本质仍是异步但语法更接近同步。

async/await 本身不改变 JavaScript 的异常处理机制,但改变了错误发生的上下文——它把异步错误“拉回”到 try/catch 可捕获的范围,从而在语法和逻辑层面实现了与同步异常处理的一致性。关键不是“一样”,而是“可统一写法”。
错误抛出位置决定能否被 try/catch 捕获
同步函数中 throw 的错误会立即中断执行,被外层 try/catch 捕获;而 async 函数内部 throw 的错误,本质是 Promise.reject(),如果不 await 就直接调用,错误不会进入当前 try/catch 块,而是变成未处理的 Promise rejection。
- ✅ 正确:在 async 函数内用 await 调用,再用 try/catch 包裹 —— 错误能被捕获,行为与同步一致
- ❌ 错误:调用 async 函数但不 await,直接放在 try/catch 里 —— finally 会先执行,错误被漏掉
- ⚠️ 注意:即使没写 await,函数返回的 Promise 仍可链式 .catch(),但这属于异步错误处理路径,和同步 try/catch 不同层
finally 的执行时机暴露了本质差异
同步代码中,try → catch → finally 是严格顺序执行;async/await 中,只有 await 真正“暂停”了函数体,才能让 finally 在错误之后运行。否则,函数立即返回 Promise,控制流跳出,finally 就成了同步执行的“旁观者”。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 同步场景:throw → catch → finally(必然按序)
- async 场景(无 await):调用 async 函数 → 立即执行 finally → 后续 Promise reject(异步触发)
- async 场景(有 await):await 触发等待 → reject → catch → finally(视觉和逻辑上回归同步节奏)
语义一致,但底层仍是异步
async/await 让你用同步风格写异步逻辑,包括错误处理结构,但它没有改变事件循环或非阻塞本质。try/catch 在 await 处生效,靠的是引擎将 Promise settle 后恢复函数执行帧,而不是真正“停住线程”。
- 堆栈更连贯:错误位置、调用链清晰,不像嵌套 .then 那样容易丢失上下文
- 调试友好:断点可以跨 await 连续命中,像写普通函数一样逐步跟进
- 但别混淆:await 不是锁,它只是告诉 JS 引擎“等这个 Promise 完了再往下走”,主线程依然自由处理其他任务
实际写法建议
要获得与同步异常处理一致的体验,必须满足两个条件:函数声明为 async,且调用处使用 await。
- 避免裸调 async 函数:thisThrows() 不加 await,就等于放任 Promise 自行 reject
- 推荐统一模式:async 函数内 + await + try/catch,这是最接近同步语义的安全组合
- 并行请求别滥用 await:多个独立 API 调用,用 Promise.all([a(), b(), c()]) + await 更高效,错误处理也需适配数组语义
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










