在JavaScript中,可以使用Promise
和async/await
结合的方式来实现限制最大并发数的并行请求。以下是几个示例代码:
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请求,并等待所有请求都完成后返回结果。
上面两个实例既然是并发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);
在JavaScript中,可以使用Promise
和async/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
。
它是一个第三方库,通常用于管理 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。