JavaScript中实现Ajax并发限制的核心是控制同时请求数不超过阈值并排队执行,常用Promise队列+计数器或信号量(Semaphore)实现;需确保错误、超时、取消时均释放许可,避免阻塞。

JavaScript 中实现 Ajax 并发数限制与排队加载,核心是**控制同时发出的请求数量不超过阈值,并将超额请求暂存、按序执行**。不依赖第三方库(如 axios 的拦截器),纯原生或轻量封装即可完成。
用 Promise 队列 + 计数器控制并发
这是最直观、易理解的方式:维护一个运行中请求数 activeCount 和待执行队列 queue,每次发起请求前检查是否已达上限;未达上限则立即执行,执行完毕后从队列取下一个;达到上限则入队等待。
示例代码:
class AjaxQueue {
constructor(max = 3) {
this.max = max;
this.activeCount = 0;
this.queue = [];
}
request(config) {
return new Promise((resolve, reject) => {
const task = () => {
this.activeCount++;
fetch(config.url, config.options || {})
.then(res => res.json())
.then(data => resolve(data))
.catch(err => reject(err))
.finally(() => {
this.activeCount--;
if (this.queue.length > 0) {
this.queue.shift()();
}
});
};
if (this.activeCount < this.max) {
task();
} else {
this.queue.push(task);
}
});
}
}
// 使用
const queue = new AjaxQueue(2);
queue.request({ url: '/api/user/1' }).then(console.log);
queue.request({ url: '/api/user/2' }).then(console.log);
queue.request({ url: '/api/user/3' }).then(console.log); // 等前两个之一完成才发
用 async/await + 信号量(Semaphore)更优雅地管理
把“并发许可”抽象为可获取/释放的信号量,逻辑更清晰,也便于复用和扩展。适合中大型项目。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- 创建一个 Semaphore 类,内部用 Promise 链模拟“许可池”
- 每次请求前 acquire(),成功后执行 fetch;完成后必须 release()
- acquire 返回 Promise,自动排队,无需手动维护队列数组
class Semaphore {
constructor(limit) {
this.limit = limit;
this.waiters = [];
this.available = limit;
}
acquire() {
if (this.available > 0) {
this.available--;
return Promise.resolve();
}
return new Promise(resolve => this.waiters.push(resolve));
}
release() {
if (this.waiters.length > 0) {
const resolve = this.waiters.shift();
resolve();
} else {
this.available++;
}
}
}
// 封装带限流的 fetch
const semaphore = new Semaphore(3);
async function limitedFetch(url, options = {}) {
await semaphore.acquire();
try {
const res = await fetch(url, options);
return res.json();
} finally {
semaphore.release();
}
}
实际使用中的关键细节
- 错误也要 release:无论成功失败,都必须调用 release,否则许可数卡死,后续请求永远阻塞
- 超时需主动清理:如果某个请求卡住(如服务无响应),应设 timeout 并在 reject 时 release,避免“许可泄漏”
- 取消请求要同步处理:若用 AbortController 取消 fetch,仍需 release,否则该次 acquire 占用的许可不会归还
- 不同业务可配不同限流值:比如图片资源用 6,并行下载;API 接口用 2,保护后端稳定性
进阶:结合 AbortController 实现排队中可取消
用户快速切换页面或输入时,可能希望取消尚未发出的排队请求(而非只取消已发出的)。可在队列中存储 { task, abortController },暴露 cancelPending 方法遍历队列调用 abort()。
这需要把队列元素从纯函数升级为含控制对象的结构,但能显著提升交互体验,尤其适用于搜索联想、实时校验等场景。

















