思路
- 创建一个请求队列,存储并发请求
- 创建一个请求调度器,用于控制请求的并发
- 设置允许的最大并发数量
- 计算当前正在执行的请求的数量
- 一个请求完成后,继续从请求队列中取出剩余的任务,调度执行
整体架构流程
请求队列:
class Queue {
// 请求队列
tasks = [];
// 将请求推入tasks队列
enqueue(task) {
this.tasks.push(task);
}
// 将请求从队列中取出
dequeue() {
return this.tasks.shift();
}
// 当前队列中的请求数量
size() {
return this.tasks.length;
}
}
请求调度器:
export class RequestScheduler {
requests = new Queue();
// 最大并发数量
maxConcurrentNum;
// 记录当前已经发送但未完成的请求数量
currentRequestNum = 0;
constructor(maxConcurrentNum = 2) {
this.maxConcurrentNum = maxConcurrentNum;
}
// 将请求添加到队列
addRequest(request) {
this.requests.enqueue(request);
this.next();
}
async next() {
if (this.requests.size() > 0) {
// 判断是否达到最大并发数
if (this.currentRequestNum < this.maxConcurrentNum) {
this.currentRequestNum++;
// 从队列中取出任务执行
const request = this.requests.dequeue();
await request();
this.currentRequestNum--;
// 任务执行完后,继续调用,看请求队列中是否还有请求未发送
this.next();
}
}
}
}
接口请求:
const requestScheduler = new RequestScheduler(3);
// 多个图片上传
const onUploadImage = (images) => {
images.forEach(async (file) => {
// 上传接口
requestScheduler.addRequest(async () => {
const res = await uploadImage(file);
console.log(res);
});
});
};
api
export const uploadImage = (img) => {
const formData = new FormData();
formData.append("image", img);
return requestClient.post("/images/upload", formData, {
headers: {
"Content-Type": "multipart/form-data",
},
});
};
小结
菜就多练
加油