在现代JavaScript开发中,异步代码并发管理是提升应用性能的关键技能。本文将通过实际案例展示如何有效控制并发数量,避免资源耗尽问题。
并发控制的核心思路
传统的Promise.all()虽然简单直接,但当请求量过大时会导致资源竞争和性能下降。我们可以通过限制同时执行的Promise数量来解决这个问题。
// 基础并发控制实现
function limitConcurrency(tasks, limit) {
return new Promise((resolve, reject) => {
if (tasks.length === 0) {
resolve([]);
return;
}
const results = [];
let index = 0;
let running = 0;
let completed = 0;
function run() {
if (completed >= tasks.length) {
resolve(results);
return;
}
while (running < limit && index < tasks.length) {
const taskIndex = index++;
running++;
tasks[taskIndex]()
.then(result => {
results[taskIndex] = result;
completed++;
running--;
run(); // 继续执行下一个任务
})
.catch(error => {
reject(error);
});
}
}
run();
});
}
// 使用示例
const urls = [
'https://api.example.com/data1',
'https://api.example.com/data2',
'https://api.example.com/data3',
'https://api.example.com/data4',
'https://api.example.com/data5'
];
const fetchTasks = urls.map(url => () => fetch(url).then(res => res.json()));
limitConcurrency(fetchTasks, 2)
.then(results => {
console.log('所有请求完成:', results);
})
.catch(error => {
console.error('请求失败:', error);
});
实际应用场景
在处理大量API请求时,合理控制并发数能有效避免服务器压力过大。比如电商网站的商品详情批量获取场景:
// 商品详情批量获取示例
async function fetchProductDetails(productIds) {
const limit = 5; // 最大并发数
const tasks = productIds.map(id => async () => {
try {
const response = await fetch(`/api/products/${id}`);
return await response.json();
} catch (error) {
console.error(`获取商品 ${id} 失败:`, error);
return null;
}
});
// 使用并发控制
const results = await limitConcurrency(tasks, limit);
return results.filter(result => result !== null);
}
// 调用示例
const productIds = Array.from({length: 20}, (_, i) => i + 1);
fetchProductDetails(productIds)
.then(products => {
console.log(`成功获取 ${products.length} 个商品详情`);
});
性能优化建议
- 合理设置并发数:根据服务器性能和网络状况调整,通常2-5为宜
- 错误处理机制:单个任务失败不应影响其他任务执行
- 进度监控:在高并发场景下提供用户反馈
通过以上方法,我们可以在保证用户体验的同时,有效管理异步请求的并发度,避免资源浪费和性能瓶颈。

讨论