单个请求
实现效果:
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()确保所有请求都完成后再返回结果。