Skip to content

实现并发请求控制 ​

在前端开发中,我们经常需要处理多个异步请求。有时候需要控制并发数量,既要保证效率,又要避免请求过多导致服务器压力过大。本文将介绍如何实现一个能够控制并发数量的请求函数。

功能特点 ​

  • 支持设置最大并发数
  • 保证响应结果的顺序与请求顺序一致
  • 异常处理机制
  • 支持 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);
});

实现原理 ​

  1. 通过 maxNum 控制最大并发数,初始启动 Math.min(maxNum, urls.length) 个请求
  2. 使用 index 记录下一个待请求的URL索引
  3. 使用 count 记录已完成的请求数量
  4. 通过数组 results 按原始顺序存储请求结果
  5. 每完成一个请求,立即启动下一个请求,保持并发数
  6. 当所有请求完成时(count === urls.length),返回结果数组

注意事项 ​

  • 该实现保证了响应结果的顺序与请求顺序一致
  • 错误会被捕获并存储在结果数组中,不会中断整个流程
  • 支持处理空数组的边界情况
  • 实际使用时建议添加请求超时处理