单个请求
实现效果:
function timeout(time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("success");
}, time);
});
}
// timeout(1000).then(res=>{
// console.log(res)
// })
class SuperTask {
constructor(paralleCount = 2) {
this.paralleCount = paralleCount; // 并发数量
this.taskList = []; // 任务列表
this.runningCount = 0; // 正在执行的任务数量
}
add(task) {
return new Promise((resolve, reject) => {
this.taskList.push({
task,
resolve,
reject,
});
this._run();
});
}
_run() {
// 依次执行任务队列里的任务
while (this.runningCount < this.paralleCount && this.taskList.length) {
// 获取任务
const { task, resolve, reject } = this.taskList.shift();
this.runningCount++;
// 执行任务
task()
.then(resolve, reject)
.finally(() => {
this.runningCount--;
this._run();
});
}
}
}
const superTask = new SuperTask();
function addTask(time, name) {
superTask
.add(() => timeout(time))
.then((res) => {
console.log(name);
});
}
addTask(1000, "1");
addTask(1000, "2");
addTask(1000, "3");
addTask(1000, "4");
addTask(1000, "5");
addTask(1000, "6");
addTask(1000, "1");
addTask(1000, "2");
addTask(1000, "3");
addTask(1000, "4");
addTask(1000, "5");
addTask(1000, "6");
-
timeout(time)
函数:- 这个函数返回一个 Promise,在指定的时间(毫秒)后会 resolve 为字符串 "success"。
-
SuperTask
类:SuperTask
类负责管理一个任务列表,并以并行的方式执行这些任务,同时限制最大并发数量。- 构造函数接受一个可选的
paralleCount
参数,用于设置最大并发任务数。 add(task)
方法将新的任务添加到任务列表中,并启动任务执行过程。_run()
方法负责从任务列表中取出任务,并在允许的并发数范围内执行这些任务。
-
addTask(time, name)
函数:- 这个函数创建一个新的任务,通过调用
superTask.add(() => timeout(time))
将任务添加到SuperTask
实例中。 - 当任务执行完成后,会打印出任务名称。
- 这个函数创建一个新的任务,通过调用
数据数组发送请求
const max = 6; // 最大请求数 const taskPool = []; // 请求队列 const formDataArray = [...formDatas]; // 创建一个副本,以免修改原始数组,原formDatas数据数组 async function uploadFiles() { const results = []; while (formDataArray.length > 0) { // 向请求池添加新的请求,直到达到最大值 while (taskPool.length < max && formDataArray.length > 0) { const formData = formDataArray.shift(); const promise = fetch("http://localhost:3000/upload", { method: "POST", body: formData, }); taskPool.push(promise); } // 等待最先完成的请求 const [firstFinishedPromise] = await Promise.race(taskPool); results.push(await firstFinishedPromise); taskPool.splice(taskPool.indexOf(firstFinishedPromise), 1); } // 等待所有请求完成 await Promise.all(taskPool); return results; } uploadFiles() .then((results) => { console.log(results); }) .catch((error) => { console.error(error); });
-
定义常量
max
,表示最大并发请求数。 -
创建
taskPool
数组用于存储当前正在执行的请求,以及formDataArray
数组用于存储待上传的文件数据。 -
定义
uploadFiles()
异步函数:-
初始化
results
数组用于存储上传结果。 -
在
formDataArray
还有未上传的文件时,进行以下操作:- 将新的请求添加到
taskPool
中,直到达到最大并发数max
。 - 使用
Promise.race()
等待最先完成的请求,并将其从taskPool
中移除,同时将结果推入results
数组。
- 将新的请求添加到
-
最后使用
Promise.all()
等待taskPool
中所有请求完成。 -
返回
results
数组。
-
-
调用
uploadFiles()
函数,并在成功和失败的情况下分别打印结果和错误信息。
这个实现的主要思路是:
- 限制并发请求数量,避免过多的请求同时发送导致资源耗尽。
- 使用
Promise.race()
等待最先完成的请求,并处理其结果。 - 使用
Promise.all()
确保所有请求都完成后再返回结果。
原文链接:https://juejin.cn/post/7406697002539483176