如果前端需要处理 100 个请求而不希望所有请求同时发出(以控制并发数),可以采用 并发控制
的方式,常用的技术包括:
- 使用 Promise.all + 自定义并发队列
通过一个自定义函数控制并发数。
// 并发控制函数
function limitConcurrency(requests, limit) {
const results = []; // 存储每个请求的结果
const executing = []; // 当前执行的请求
for (const request of requests) {
const p = Promise.resolve().then(() => request());
results.push(p);
// 添加到执行队列
if (limit <= requests.length) {
const e = p.then(() => executing.splice(executing.indexOf(e), 1));
executing.push(e);
// 当并发数达到限制时,等待最早的 Promise 完成
if (executing.length >= limit) {
await Promise.race(executing);
}
}
}
// 等待所有任务完成
return Promise.all(results);
}
// 示例请求函数
const createRequest = (id, delay) => () => {
return new Promise((resolve) => {
setTimeout(() => {
console.log(`Request ${id} completed`);
resolve(`Result ${id}`);
}, delay);
});
};
// 构造 100 个请求,每个请求有不同的延迟
const requests = Array.from({ length: 100 }, (_, i) => createRequest(i + 1, Math.random() * 1000));
// 调用并发控制函数,限制最大并发数为 5
limitConcurrency(requests, 5).then((results) => {
console.log('All requests completed');
console.log(results);
});
代码说明
-
limitConcurrency
函数:-
接受两个参数:
requests
:由请求函数组成的数组(每个函数返回一个 Promise)。limit
:最大并发数。
-
使用一个执行队列 (
executing
) 来追踪当前执行的 Promise。 -
如果并发数达到
limit
,通过Promise.race
等待最早完成的请求。
-
-
示例请求:
createRequest
模拟请求,使用setTimeout
模拟不同的延迟。
-
调用:
- 通过
limitConcurrency(requests, 5)
将 100 个请求的并发数限制为 5。
- 通过
- 使用第三方库 p-limit
如果想使用现成的工具,p-limit
是一个轻量级的库,专门用于限制并发数。
安装
npm install p-limit
使用示例
import pLimit from 'p-limit';
const limit = pLimit(5); // 设置并发数为 5
// 模拟 100 个请求
const tasks = Array.from({ length: 100 }, (_, i) =>
limit(() =>
new Promise((resolve) => {
setTimeout(() => {
console.log(`Request ${i + 1} completed`);
resolve(`Result ${i + 1}`);
}, Math.random() * 1000);
})
)
);
// 执行所有任务
Promise.all(tasks).then((results) => {
console.log('All requests completed');
console.log(results);
});