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);

在上面的示例代码中,我们首先使用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);
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();

这个示例使用了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

然后,你可以像这样使用 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}`);
  });
});

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

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 好的,以下是一个简单的控制请求并发js: ```javascript function limitRequestConcurrency(urls, maxConcurrency, callback) { let activeRequests = ; let index = ; function next() { if (index === urls.length && activeRequests === ) { return; } while (activeRequests < maxConcurrency && index < urls.length) { const url = urls[index++]; activeRequests++; fetch(url) .then(response => response.json()) .then(data => { callback(data); }) .catch(error => { console.error(error); }) .finally(() => { activeRequests--; next(); }); } } next(); } ``` 这个函接受三个参: - `urls`:一个包含请求URL的组。 - `maxConcurrency`:最大并发请求。 - `callback`:请求成功后的回调函,接受一个参,即请求返回的据。 函内部使用了递归调用来控制并发,当活跃请求小于最大并发时,就会发起新的请求,否则等待已有请求完成后再发起新的请求。 ### 回答2: 可以使用以下的JavaScript来控制请求并发: ```javascript function controlConcurrency(requests, maxConcurrent) { const results = []; let currentConcurrent = 0; let i = 0; function handleRequest() { if (i >= requests.length) { // 所有请求处理完毕 return; } if (currentConcurrent >= maxConcurrent) { // 达到最大并发,等待一段时间再处理下一个请求 setTimeout(handleRequest, 100); return; } // 处理请求 const request = requests[i]; const promise = request(); currentConcurrent++; promise .then(response => { // 处理请求结果 results.push(response); }) .finally(() => { // 无论请求成功或失败,都将并发减1,然后处理下一个请求 currentConcurrent--; i++; handleRequest(); }); } // 开始处理请求 handleRequest(); // 返回Promise对象,当所有请求处理完毕时,将结果组作为resolve参 return new Promise(resolve => { setTimeout(() => { if (i >= requests.length && currentConcurrent === 0) { resolve(results); } }, 1000); // 超时时间,避免请求处理时间过长导致无法结束Promise }); } ``` 这个函接收两个参:`requests`和`maxConcurrent`。`requests`是一个包含多个请求组,每个请求应该返回一个Promise对象。`maxConcurrent`表示最大并发。 函会按照最大并发依次处理请求,当达到最大并发时,会等待一段时间再继续处理下一个请求。处理请求的过程使用递归实现,直到所有请求都处理完毕。 函返回一个Promise对象,在所有请求处理完毕时,将结果组作为resolve参传递。你可以使用`.then()`方法来处理最终的结果。 ### 回答3: 当需要控制请求并发时,可以使用以下的 JavaScript来实现: ```javascript function requestControlledConcurrency(urls, maxConcurrentRequests) { return new Promise((resolve, reject) => { let currentIndex = 0; let activeRequests = 0; let completedRequests = 0; let results = []; function makeRequest(url) { activeRequests++; return fetch(url) .then(response => { activeRequests--; completedRequests++; results.push(response); if (completedRequests === urls.length) { resolve(results); } else { processNextRequest(); } }) .catch(error => { reject(error); }); } function processNextRequest() { while (activeRequests < maxConcurrentRequests && currentIndex < urls.length) { makeRequest(urls[currentIndex]); currentIndex++; } } processNextRequest(); }); } ``` 这个函接受两个参:`urls` 是一个包含多个请求 URL 的组,`maxConcurrentRequests` 是允许的最大并发请求。函会返回一个 Promise 对象,成功时返回包含所有请求结果的组,失败时返回错误信息。 这个函会依次发起请求,同时保持活动请求不超过设定的最大并发请求。在每次请求完成后,会判断是否还有未完成的请求,如果有则继续发起新的请求。只有当所有请求都完成后,Promise 才会被解析并返回结果组。 可以按照以下示例使用这个函: ```javascript const urls = ['url1', 'url2', 'url3', 'url4', 'url5']; const maxConcurrentRequests = 2; requestControlledConcurrency(urls, maxConcurrentRequests) .then(results => { console.log('所有请求完成'); console.log(results); }) .catch(error => { console.error('请求失败'); console.error(error); }); ``` 这个示例中,将同时发起两个请求,并且保持同时进行的请求不超过两个,直到所有请求完成。完成后,将会打印出所有请求的结果组。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值