控制同时进行的请求数量代码实现
async function runWithConcurrency(tasks, maxConcurrent) {
if (!Array.isArray(tasks) || tasks.length === 0) {
return [];
}
if (maxConcurrent <= 0) {
throw new Error('maxConcurrent 必须大于 0');
}
const results = [];
const activePromises = new Set();
const executeTask = async (task, index) => {
try {
const result = await task();
return { index, status: 'fulfilled', value: result };
} catch (error) {
return { index, status: 'rejected', reason: error };
}
};
const waitForAnyTask = async () => {
if (activePromises.size === 0) return;
await Promise.race(activePromises);
};
const cleanupCompletedTasks = () => {
for (const promise of activePromises) {
if (promise.status === 'fulfilled' || promise.status === 'rejected') {
activePromises.delete(promise);
}
}
};
for (let i = 0; i < tasks.length; i++) {
const task = tasks[i];
while (activePromises.size >= maxConcurrent) {
await waitForAnyTask();
cleanupCompletedTasks();
}
const taskPromise = executeTask(task, i);
activePromises.add(taskPromise);
results.push(taskPromise);
taskPromise.finally(() => {
activePromises.delete(taskPromise);
});
}
return Promise.allSettled(results);
}
const userIds = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const fetchUser = (id) => {
return new Promise((resolve, reject) => {
const delay = Math.random() * 2000 + 500;
setTimeout(() => {
if (Math.random() < 0.1) {
reject(new Error(`获取用户 ${id} 失败`));
} else {
resolve({ id, name: `用户${id}`, delay: Math.round(delay) });
}
}, delay);
});
};
const tasks = userIds.map(id => () => fetchUser(id));
async function testConcurrency() {
console.log('开始执行并发任务,最大并发数:3');
console.log('任务总数:', tasks.length);
const startTime = Date.now();
try {
const results = await runWithConcurrency(tasks, 3);
const endTime = Date.now();
const totalTime = endTime - startTime;
console.log(`\n所有任务完成!总耗时: ${totalTime}ms`);
console.log('结果统计:');
const fulfilled = results.filter(r => r.status === 'fulfilled').length;
const rejected = results.filter(r => r.status === 'rejected').length;
console.log(`成功: ${fulfilled}, 失败: ${rejected}`);
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
console.log(`任务 ${index + 1}: ✅ ${JSON.stringify(result.value)}`);
} else {
console.log(`任务 ${index + 1}: ❌ ${result.reason.message}`);
}
});
} catch (error) {
console.error('执行过程中发生错误:', error);
}
}
testConcurrency();
- 这个函数会确保最多只有maxConcurrent个请求同时在进行。
- 当一个请求完成,池子里有空位了,才会开始下一个请求。