javascript循环中async/await的关键是区分串行、并行与可控并发:串行用for...of确保顺序;并行用promise.all()提升效率;大量任务需限并发防崩溃;foreach/map等高阶函数不支持await暂停。

在 JavaScript 循环中用 async/await 处理异步操作,关键不是“能不能写”,而是“想串行还是并行”——选错方式会导致结果顺序错乱、逻辑阻塞或资源浪费。下面分场景讲清楚怎么选、怎么写、怎么避坑。
串行执行:一个接一个,等前一个完成再开始下一个
适合有依赖关系、需严格顺序、或避免并发压力的场景(比如依次调用 API 更新状态、逐个写文件)。
- 必须用
for...of、for或while循环,不能用forEach、map等高阶函数 -
await写在循环体内,直接等待每次异步调用结束 - 代码简洁直观,调试友好,错误可被统一
try/catch捕获
示例:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
for (const item of items) {
try {
const res = await fetchItem(item);
console.log(res);
} catch (err) {
console.error(`处理 ${item} 失败`, err);
}
}
}
并行执行:全部同时发起,最后统一收尾
适合无依赖、追求效率的场景(如批量拉取用户资料、预加载多个资源)。
- 用
map创建 Promise 数组,每个回调标记为async - 用
Promise.all()等待所有 Promise 完成;失败时会短路(任一拒绝即整体失败) - 若需容错(某个失败不影响其余),改用
Promise.allSettled()
示例:
async function parallelProcess(items) {const promises = items.map(async item => {
return await fetchItem(item);
});
try {
const results = await Promise.all(promises);
return results;
} catch (err) {
throw new Error('任一请求失败,整体中断');
}
}
可控并发:限制同时运行数量,兼顾速度与稳定性
面对大量任务(比如 100 个 HTTP 请求),全量并行可能触发限流或内存溢出,这时需要节流。
- 不用
Promise.all,改用队列 + 信号量控制并发数 - 常见做法:每次最多启动 N 个 Promise,空闲时补上新任务
- 可用第三方库(如
p-limit),也可手写简易版
简易实现思路:
async function limitedParallel(items, limit = 3) {const results = [];
const executing = [];
for (const item of items) {
const p = fetchItem(item).then(res => {
results.push(res);
return res;
});
executing.push(p);
if (executing.length >= limit) {
await Promise.race(executing);
executing.splice(0, 1);
}
}
await Promise.all(executing);
return results;
}
别踩的坑:forEach、map、filter 都不直接支持 await
这些数组方法的回调是同步执行的,即使加了 async,也只是返回 Promise 而不会暂停外层流程。
-
items.forEach(async item => await api(item))→ 所有请求立刻发出,不等结果,外层函数很快结束 -
items.map(async item => await api(item))→ 返回的是 Promise 数组,不是数据数组 - 误以为“写了 await 就串行了”,实际只是语法合法、语义失效
记住:只有能暂停执行的结构(for 类循环)才真正响应 await。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










