在JavaScript开发中,使用async/await结合fetch处理循环中的异步请求是非常常见的需求,比如批量获取用户数据或依次提交表单。合理的写法能提升性能并避免逻辑错误。

为什么循环中直接用forEach有问题
很多初学者会尝试在forEach的回调里使用async函数,但forEach并不会等待异步完成,也无法用await控制顺序。如下代码并不会按顺序输出结果:
const urls = ['/api/a', '/api/b', '/api/c'];
urls.forEach(async (url) => {
const res = await fetch(url);
const data = await res.json();
console.log(data);
});
上面的请求会几乎同时发出,且外部无法感知全部完成时机。
顺序执行:使用for循环
如果业务要求严格按顺序请求,可使用for...of配合await:
async function sequentialFetch(urls) {
const results = [];
for (const url of urls) {
const res = await fetch(url);
const data = await res.json();
results.push(data);
}
return results;
}
这种方式逻辑清晰,但总耗时是所有请求之和。
并发执行:使用Promise.all
当请求之间无依赖时,推荐并发处理以提升速度:
async function parallelFetch(urls) {
const promises = urls.map(url => fetch(url).then(res => res.json()));
return Promise.all(promises);
}
注意若某个请求失败,Promise.all会整体拒绝,需要自行捕获。
控制并发数量
请求过多时可用队列限制并发,例如简单实现:
async function limitFetch(urls, limit = 2) {
const results = [];
const executing = [];
for (const url of urls) {
const p = fetch(url).then(res => res.json());
results.push(p);
const e = p.then(() => executing.splice(executing.indexOf(e), 1));
executing.push(e);
if (executing.length >= limit) {
await Promise.race(executing);
}
}
return Promise.all(results);
}
小结
实践中应根据依赖关系选择顺序或并发,并关注错误边界与并发上限,才能写出稳健的异步循环代码。
async_awaitfetch循环异步修改时间:2026-07-29 10:54:15