如何限制同时发起的 fetch 请求数量?

司马艳艳 阅读 155

我有个页面要加载几十个用户头像,每个头像都要单独请求接口。现在一进来就同时发几十个 fetch,浏览器卡死了,怎么控制并发数啊?

试过用 Promise.all,但好像更糟了,所有请求还是同时发出去。想实现类似“最多同时发5个,一个完成再发下一个”这种效果,但不知道咋写。

<div id="avatar-container">
  <!-- 动态插入 img 标签,每个 src 对应一个 /api/avatar/:id 接口 -->
</div>
<script>
  const ids = Array.from({length: 30}, (_, i) => i + 1);
  ids.forEach(id => {
    fetch(/api/avatar/${id})
      .then(res => res.blob())
      .then(blob => {
        const url = URL.createObjectURL(blob);
        const img = document.createElement('img');
        img.src = url;
        document.getElementById('avatar-container').appendChild(img);
      });
  });
</script>
我来解答 赞 6 收藏
二维码
手机扫码查看
1 条解答
UX-康平
UX-康平 Lv1
这种并发控制问题我处理过很多次了,给你个现成的方案。核心思路是用队列 + 递归的方式控制并发数。

const ids = Array.from({length: 30}, (_, i) => i + 1);
const maxConcurrent = 5; // 最大并发数
let currentCount = 0;

async function fetchAvatar(id) {
currentCount++;
try {
const res = await fetch(/api/avatar/${id});
const blob = await res.blob();
const url = URL.createObjectURL(blob);
const img = document.createElement('img');
img.src = url;
document.getElementById('avatar-container').appendChild(img);
} finally {
currentCount--;
processQueue();
}
}

function processQueue() {
while (currentCount < maxConcurrent && ids.length > 0) {
const id = ids.shift();
fetchAvatar(id);
}
}

// 启动
processQueue();


直接复制过去试试。原理很简单:
1. 维护一个请求计数器
2. 每次请求完成就减计数器
3. 只要还有剩余并发额度就从队列取新任务
4. 初始调用一次启动整个流程

这个方案比Promise.all靠谱多了,不会一次性全发出去。
点赞 4
2026-03-05 13:05