异步数组请求应据需求选方案:串行用for...of+await,并行用promise.all(),限并发用async-pool或手写控制;避免foreach+async、for...in及忽略错误处理。

在异步函数中遍历处理数组请求,关键不是“能不能用 for 循环”,而是“要不要等每个请求完成再继续”——这直接决定该用 for...of + await,还是 Promise.all(),或是带控制的并发方案。
需要串行执行(一个接一个发请求)
适合依赖前序结果、避免接口限流、或服务端不支持并发的场景。用 for...of 配合 await 最清晰:
async function fetchSequential(urls) {
const results = [];
for (const url of urls) {
try {
const res = await fetch(url);
const data = await res.json();
results.push(data);
} catch (err) {
console.warn(`请求失败 ${url}:`, err.message);
results.push(null); // 或跳过、抛出等
}
}
return results;
}
- 每次循环都会暂停,等当前请求 resolve 后才进入下一轮
- 错误不会中断整个流程,可按需处理(如记录、填充默认值)
- 注意:不要用
forEach+async回调——它不会等待,相当于发起所有请求但不等结果
需要并行执行(同时发所有请求)
适合请求彼此独立、追求最快速度、且后端能承受并发压力的场景。优先用 Promise.all():
async function fetchParallel(urls) {
const promises = urls.map(async url => {
try {
const res = await fetch(url);
if (!res.ok) throw new Error(`${res.status}`);
return res.json();
} catch (err) {
throw new Error(`请求 ${url} 失败: ${err.message}`);
}
});
try {
return await Promise.all(promises);
} catch (err) {
// 任一失败则整体 reject,如需部分失败仍返回成功项,改用 Promise.allSettled
throw err;
}
}
-
Promise.all()会同时触发所有请求,但返回结果顺序与输入数组一致 - 若允许部分失败,换用
Promise.allSettled(),它总是 resolve,返回每个 promise 的状态对象 - 避免在
map内直接await——那又变回串行了
需要限制并发数(比如最多同时 3 个请求)
兼顾速度与稳定性,防止压垮客户端或服务端。可用 async-pool 库,或手写简易控制:
async function fetchWithLimit(urls, limit = 3) {
const results = [];
const executing = [];
for (const url of urls) {
const promise = fetch(url)
.then(res => res.json())
.catch(err => ({ error: err.message }));
results.push(promise);
if (limit > 0) {
const e = promise.then(() => executing.splice(executing.indexOf(e), 1));
executing.push(e);
if (executing.length >= limit) await Promise.race(executing);
}
}
return Promise.all(results);
}
- 更推荐使用成熟库如
async-pool,语义明确、边界处理完善 - 手写时核心是“维持运行中 promise 数量 ≤ 限制”,用
Promise.race()等待任一完成再加新任务 - 注意异常处理和结果顺序保持——
Promise.all()仍可包裹最终结果数组
别踩这些坑
-
不用
for...in遍历数组:它遍历的是属性名(包括原型链),不是索引 -
避免
async+forEach:forEach不识别await,内部async回调会立即返回 pending promise -
注意
Promise.all()的“全成功”特性:一个 reject 就让整个失败,不符合需求时换allSettled -
记得处理网络错误和 HTTP 状态码:fetch 成功不代表响应有效,
res.ok和res.status要检查
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











