Promise实现带并发限制的异步加载器,核心是资源池模型:最多n个任务并行,用running计数+队列调度,完成一个再启下一个;支持超时、重试、取消等进阶能力。

用 Promise 实现带并发限制的异步加载器,核心是控制同时执行的 Promise 数量不超过设定上限,等有任务完成后再调度下一个。不依赖第三方库,纯原生 JavaScript 即可实现。
基本思路:维护一个运行中任务队列
关键不是“节流”或“防抖”,而是“资源池”模型:最多允许 n 个异步操作并行执行;新任务提交时,如果当前运行数
实现一个通用的并发控制函数 limitRun
这个函数接收任务数组和最大并发数,返回一个 Promise 数组(顺序与输入一致):
function limitRun(tasks, limit) {
const results = [];
let running = 0; // 当前正在执行的任务数
let index = 0; // 下一个待执行任务的索引
const promises = [];
// 递归调度函数
function next() {
if (index >= tasks.length && running === 0) return;
while (running < limit && index < tasks.length) {
const task = tasks[index++];
running++;
const promise = Promise.resolve(task()).then(
res => {
results.push({ status: 'fulfilled', value: res });
},
err => {
results.push({ status: 'rejected', reason: err });
}
).finally(() => {
running--;
next(); // 尝试调度下一个
});
promises.push(promise);
}
}
next();
return Promise.all(promises).then(() => results);
}
使用示例:并发加载 10 个图片 URL,最多同时 3 个请求
假设你有一组图片 URL,想批量 fetch 并确保不压垮浏览器或服务端:
立即学习“Java免费学习笔记(深入)”;
const urls = [
'/img/1.jpg',
'/img/2.jpg',
// ... 共 10 个
];
const fetchImg = url => () =>
fetch(url)
.then(res => res.blob())
.then(blob => URL.createObjectURL(blob));
limitRun(urls.map(fetchImg), 3)
.then(results => {
// results 是按顺序的 { status, value/reason } 数组
console.log('全部完成,成功', results.filter(r => r.status === 'fulfilled').length);
});
进阶:支持取消、超时、重试等能力
基础版已满足多数场景。如需增强,可在每个 task 包装层加入:
- 超时:用 Promis.e race([task(), new Promise(...)])
- 重试:在 .catch() 中判断错误类型,递归调用自身(注意限制次数)
- 取消:借助 AbortController(需 task 支持 signal 参数)
但注意:取消不会自动中断已发出的 fetch 请求(仅阻止后续处理),真正终止需后端配合。


















