• JS多个HTTP请求限制最大并发数


    在JavaScript中,可以使用Promiseasync/await结合的方式来实现限制最大并发数的并行请求。以下是几个示例代码:

    1、实例一:
    const arr = Array.from({ length: 100 }, (value, index) => index + 1); // 生成一个包含100个元素的数组
    
    // 模拟一个异步请求,每个请求用Promise包装
    const fetchData = (num) => {
      return new Promise((resolve) => {
        setTimeout(() => {
          console.log('Request', num, 'finished');
          resolve();
        }, Math.random() * 1000); // 使用随机的延迟模拟请求时间
      });
    };
    
    const sendRequest = async (urls, concurrentLimit) => {
      const tasks = urls.map((url) => fetchData(url));
      const results = [];
    
      for (let i = 0; i < tasks.length; i += concurrentLimit) {
        const currentTasks = tasks.slice(i, i + concurrentLimit);
        await Promise.all(currentTasks).then((result) => {
          results.push(...result);
          console.log('Batch finished:', i + concurrentLimit);
        });
      }
    
      console.log('All requests completed');
      return results;
    };
    
    sendRequest(arr, 10);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    在上面的示例代码中,我们首先使用Array.from方法生成了一个包含100个元素的数组。然后,我们使用fetchData函数模拟了一个异步请求,并将每个请求用Promise包装起来。

    接下来,我们定义了一个sendRequest函数来发送请求。该函数接受两个参数:urls是要发送请求的数组,concurrentLimit是限制的最大并发数。

    在函数内部,我们使用map方法将每个请求任务封装成Promise对象并保存在tasks数组中。然后,我们使用for循环来分批处理请求任务。每次循环从tasks数组中取出concurrentLimit个任务,并使用Promise.all方法来等待这些任务完成。一旦每一批任务都完成,我们会将结果保存到results数组中,并输出一条批次完成的消息。

    最后,我们在sendRequest函数的最后输出一条所有请求完成的消息,并返回results数组。

    通过这种方式,我们可以限制最大并发数为10,快速发送100个HTTP请求,并等待所有请求都完成后返回结果。

    2、改进机制

    上面两个实例既然是并发100个请求,第一个用.all的方式效率就太低了,假如第一组有一个请求非常慢,那会导致9个并发位置的空闲

    下面是改进后的代码:

    const arr = [];
    for (let i = 0; i < 100; i++) {
      arr.push(() => new Promise((resolve) => {
        setTimeout(() => {
          console.log('done', i);
          resolve();
        }, 100 * i);
      }));
    }
    
    const parallelRun = () => {
      const runningTask = new Map();
      
      const enqueue = (totalTask, max) => {
        while (runningTask.size < max && totalTask.length) {
          const newTask = totalTask.shift();
          const tempName = totalTask.length;
          runningTask.set(tempName, newTask);
          newTask().finally(() => {
            runningTask.delete(tempName);
            enqueue(totalTask, max);
          });
        }
      }
      
      return enqueue;
    };
    
    parallelRun()(arr, 6);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    4、借助第三方库实现

    在JavaScript中,可以使用Promiseasync/await来控制并发请求的数量。以下是一个示例代码,该代码将限制最大并发请求数为10:

    const axios = require('axios');
    const semaphore = require('semaphore');
    
    const sem = semaphore(10);
    const urls = [/* 你的URL列表 */];
    
    async function fetchUrl(url) {
      await sem.take();
      try {
        const response = await axios.get(url);
        console.log(response.data);
      } catch (error) {
        console.error(error);
      } finally {
        sem.leave();
      }
    }
    
    async function fetchAllUrls() {
      await Promise.all(urls.map(fetchUrl));
    }
    
    fetchAllUrls();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    这个示例使用了semaphore库来创建一个信号量,以限制并发请求的数量。semaphore.take()方法会检查当前是否有可用的许可证,如果有则返回一个Promise,该Promise在许可证被释放时解析。在请求完成之后,使用semaphore.leave()释放许可证,允许其他请求继续进行。

    注意:你需要先通过npm安装semaphore库:npm install semaphore

    5、借助三方库limit

    它是一个第三方库,通常用于管理 Promise 并发。

    以下是使用 p-limit 的基本示例:

    首先,你需要安装 p-limit。你可以使用 npm(Node Package Manager)来安装:

    npm install p-limit
    
    • 1

    然后,你可以像这样使用 p-limit

    const { limit, Promise } = require('p-limit');
    
    // 创建一个限制执行数量的 limit 对象
    const limitObj = limit(10);
    
    // 创建一个异步函数,该函数返回一个 Promise
    async function asyncFunction(value) {
      return new Promise((resolve) => {
        setTimeout(() => {
          console.log(`Resolving ${value}`);
          resolve(value);
        }, 1000);
      });
    }
    
    // 使用 limit 对象来控制并发执行
    limitObj.acquire().then(() => {
      asyncFunction('example').then((value) => {
        console.log(`Finished processing ${value}`);
      });
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在上述代码中,我们创建了一个 limit 对象,该对象限制了同时执行的 Promise 数量。然后我们创建了一个异步函数 asyncFunction,该函数返回一个 Promise。最后,我们使用 limitObj.acquire() 来获取一个可用的 Promise,然后立即执行 asyncFunction。一旦该 Promise 完成,我们就可以继续处理下一个可用的 Promise。

  • 相关阅读:
    thinkphp6(TP6)访问控制器报404(Nginx)
    .balckhoues-V-XXXXXXX勒索病毒数据怎么处理|数据解密恢复
    2000-2020全要素生产率OP法+LP法+OLS和固定效应法三种方法合集含原始数据和计算过程Stata代码
    代码随想录刷题记录 6 - 二叉树(1)
    尚硅谷大数据项目《在线教育之离线数仓》笔记008
    结构体的内存对齐
    SAP S4 FI 后台详细配置教程文档 PART2 (财务会计的基本设置篇)
    jxTMS设计思想之流程追溯
    MySQL逻辑架构
    一个简单HTML5期末考核大作业,学生个人html静态网页制作代码
  • 原文地址:https://blog.csdn.net/weixin_36445197/article/details/132739459