编写健壮的 async/await 代码需主动异常处理、明确控制流边界、避免隐式错误传播;每个 await 应显式捕获,避免 unhandled rejection;独立 I/O 操作应并发执行;资源须在 finally 清理;函数职责清晰,返回类型统一。

编写健壮的 async/await 代码,核心在于主动处理异常、明确控制流边界、避免隐式错误传播,而不是仅仅把 Promise 链改成 await 语法糖。
用 try/catch 显式捕获每个可能失败的 await 点
await 不会自动抛出错误到上层作用域,未捕获的 Promise rejection 会变成 unhandled rejection,影响稳定性。
- 不要只在函数最外层包一层 try/catch——如果中间多个 await 有不同恢复策略(比如重试、降级、记录),需分别处理
- 对网络请求、文件读写、数据库操作等 I/O 操作,每个 await 都应有对应 catch 或使用
await Promise.resolve().catch(...)快速兜底 - 示例:调用 API 失败后返回默认值,而非让整个函数中断
避免 await 在循环中无节制地串行执行
for 循环里逐个 await 是常见性能陷阱,尤其当任务彼此独立时,会把本可并发的操作强制变串行。
- 用
Promise.all()并发执行多个独立异步任务,再统一 await 结果数组 - 若需控制并发数(如防止请求打爆服务),可用 p-limit、p-map 等工具库,或手写滑动窗口逻辑
- 注意:Promise.all() 遇错即停;需要“全量执行+收集结果(含错误)”,改用
Promise.allSettled()
始终清理资源,尤其涉及定时器、监听器、连接等
async 函数退出不等于异步操作终止。未清理的定时器、事件监听器、socket 连接会持续占用内存并引发意外交互。
- 在 try 中启动资源,在 finally 中释放(即使 await 报错也要清理)
- 对可取消的异步操作(如 fetch + AbortController),把 signal 传入并监听取消时机
- Node.js 中注意 stream 的 close/end 事件,前端注意 addEventListener 后及时 removeEventListener
函数职责清晰,不混用 async 和同步逻辑边界
一个函数要么是 async(返回 Promise),要么是 sync(返回普通值),避免“半 async”设计——比如部分路径 return Promise,部分 return 原始值。
- 不要在 async 函数里直接 return 一个未 await 的 Promise,这会让调用方难以判断返回值类型
- 不要为“看起来像异步”的同步计算(如 JSON.parse、简单数组过滤)加 async/await,徒增开销和理解成本
- 对外暴露的接口,类型要稳定:如果声明了 async,就始终返回 Promise;若内部有分支可能同步完成,用
Promise.resolve(value)统一包装
不复杂但容易忽略。关键不是写得“像异步”,而是让异步行为可预测、可中断、可恢复、可追踪。


















