async/await的核心价值在于使异步逻辑线性化、可读且易调试;关键在于正确使用:函数应直接返回值或promise,避免冗余await和promise包装,合理利用promise.all实现并发,显式try/catch处理错误,并分步重构回调代码。

async/await 的核心价值在于让异步逻辑回归线性、可读、易调试的形态。写得好,它比 Promise 链更清晰;写得随意,反而会掩盖并发意图、拖慢执行、埋下错误隐患。关键不在“用不用”,而在“怎么用才对”。
函数声明与返回值要干净
async 函数天然返回 Promise,无需手动包装:
- ✅ 正确:直接 return 原始值或同步表达式,如 async () => 'done' 或 async () => fetch(url)
- ❌ 避免:async () => Promise.resolve(value) —— 多一层封装,无意义
- ❌ 避免:async () => { return await someAsync() } —— return await 不仅冗余,还会延迟函数 resolve 时间,影响调用方感知
- ✅ 更优写法:async () => someAsync()(让调用方决定何时 await)
await 的时机决定并发行为
是否提前创建 Promise,直接影响是串行还是并行:
- ❌ 串行等待(耗时叠加):
await api.getUser();
await api.getPosts();
await api.getComments(); - ✅ 并行发起(总耗时趋近最长项):
const [user, posts, comments] = await Promise.all([
api.getUser(),
api.getPosts(),
api.getComments()
]); - ✅ 按需混合:部分依赖、部分独立时,先发独立请求,再 await 依赖链
const user = api.getUser();
const settings = api.getSettings();
const profile = await api.getProfile();
return { user: await user, settings: await settings, profile };
错误处理必须显式覆盖每个 await 点
await 会把 rejected Promise 变成 throw,但只在当前 async 函数内生效。漏掉 try/catch 就等于让错误穿透到上层:
- ✅ 推荐结构:
try {
const data = await fetch('/api');
const json = await data.json();
return json;
} catch (err) {
console.error('API 调用失败', err);
throw new Error('加载失败,请重试');
} - ⚠️ 注意:单个 try/catch 覆盖多个 await 是安全的,但不要假设“前面没报错,后面就一定成功”——网络中断、JSON 解析失败、空响应等都可能在不同位置抛出
- ✅ 对于可容忍失败的步骤(如埋点上报),可用 void (async () => { /* 忽略错误 */ })(); 避免阻塞主流程
重构回调代码的关键节奏
从回调地狱迁移到 async/await,不是一气呵成改完,而是分三步稳扎稳打:
- 第一步:把每个回调函数包装成返回 Promise 的工具函数(如 fs.promises.readFile 或自定义 readFileAsync)
- 第二步:找到最外层回调入口,将其改为 async 函数,并逐层替换内部 callback(err, result) 为 return result 或 throw err
- 第三步:合并嵌套逻辑,用 for / for-of / if-else 替代 forEach + 回调,消除“pending 计数器”这类手工状态管理
不复杂但容易忽略:async/await 不是魔法,它只是 Promise 的语法糖。真正提升质量的,是你对任务依赖关系的判断、对错误边界的划分,以及对并发意图的诚实表达。











