实现并发请求控制
在前端开发中,我们经常需要处理多个异步请求。有时候需要控制并发数量,既要保证效率,又要避免请求过多导致服务器压力过大。本文将介绍如何实现一个能够控制并发数量的请求函数。
功能特点
- 支持设置最大并发数
- 保证响应结果的顺序与请求顺序一致
- 异常处理机制
- 支持 Promise 方式调用
代码实现
javascript
function concurRequest(urls, maxNum) {
return new Promise(resolve => {
// 处理空数组的边界情况
if (urls.length === 0) {
resolve([]);
return;
}
const results = []; // 存储请求结果
let index = 0; // 下一个待请求的下标
let count = 0; // 已完成的请求数量
// 发起单个请求的函数
async function request() {
if (index === urls.length) return;
const currentIndex = index;
const url = urls[index++];
try {
const response = await fetch(url);
results[currentIndex] = response; // 按原始顺序存储结果
} catch (error) {
results[currentIndex] = error; // 存储错误信息
} finally {
count++;
// 所有请求完成时,返回结果数组
if (count === urls.length) {
resolve(results);
return;
}
// 继续下一个请求
request();
}
}
// 启动初始的并发请求
const concurrentNum = Math.min(maxNum, urls.length);
for (let i = 0; i < concurrentNum; i++) {
request();
}
});
}使用示例
javascript
const urls = [
'https://api.example.com/data1',
'https://api.example.com/data2',
'https://api.example.com/data3',
'https://api.example.com/data4'
];
// 最多同时发起2个请求
concurRequest(urls, 2).then(results => {
console.log('所有请求完成:', results);
});实现原理
- 通过
maxNum控制最大并发数,初始启动Math.min(maxNum, urls.length)个请求 - 使用
index记录下一个待请求的URL索引 - 使用
count记录已完成的请求数量 - 通过数组
results按原始顺序存储请求结果 - 每完成一个请求,立即启动下一个请求,保持并发数
- 当所有请求完成时(
count === urls.length),返回结果数组
注意事项
- 该实现保证了响应结果的顺序与请求顺序一致
- 错误会被捕获并存储在结果数组中,不会中断整个流程
- 支持处理空数组的边界情况
- 实际使用时建议添加请求超时处理