循环内使用 await 会导致串行执行,大幅增加耗时;仅当前操作强依赖前序结果时才适用,多数场景应改用 Promise.all 并行处理。

await 在循环体内串行执行会显著拖慢整体耗时,本质是把本可并行的操作强制变成顺序等待。它不是语法错误,但常被误用为“自然写法”,导致接口响应变慢、用户体验下降。
为什么循环里 await 会变慢?
每次遇到 await,JavaScript 会暂停当前 async 函数的执行,等 Promise settle 后才继续下一轮循环。哪怕每个异步操作彼此独立(比如调用不同用户的 API),也必须一个接一个等下去。
- 10 次请求,每次 200ms → 串行要 2000ms
- 同样 10 次请求 → 并行通常只需略多于 200ms
- 时间差可达 10 倍,且请求数越多越明显
什么情况适合在循环里用 await?
仅当后续操作强依赖前一次结果时才合理,例如:
- 分页拉取数据,下一页 URL 来自上一页响应体
- 逐个上传文件,后一个需等前一个返回的 token 或校验结果
- 状态机式流程:A 成功后才执行 B,B 失败则终止整个流程
如何改写成高效并行?
多数场景应把循环转为数组映射 + Promise.all(或 Promise.allSettled):
立即学习“Java免费学习笔记(深入)”;
// ❌ 串行(慢)
for (const id of ids) {
const res = await fetch(`/api/user/${id}`);
results.push(await res.json());
}
// ✅ 并行(快)
const promises = ids.map(id =>
fetch(`/api/user/${id}`).then(r => r.json())
);
results = await Promise.all(promises);
若需控制并发数(防请求打爆服务),可用 p-limit 库或手写批处理逻辑,不直接用 for + await。
容易忽略的细节
-
Promise.all遇到任一失败就 reject,如需全量结果,改用Promise.allSettled - 循环中修改共享变量(如 push 到同一数组)在并行下仍安全,因 map 返回的是独立 Promise 队列
- for-await-of 适用于异步迭代器(如 ReadableStream),不等于“让 for 循环变并行”











