描述
实现一个任务队列和执行队列,执行队列只能同时执行一些任务,当某一个任务执行完成后才会从任务队列中去取出一条任务去执行
应用场景
例如前端大文件上传功能经常会用到分片上传,假如单片2Mb,1G文件上传需要上传512次,单片单片上传速度很慢,一次性并发数又太高,这时候能将并发请求控制在一定数量内,既能保证传输速度又可以不过高损耗服务器性能
实现
首先我们先用一个定时器函数模拟接口请求
function _timeout(time) {
return new Promise((reslove, reject) => {
setTimeout(() => {
reslove();
}, time);
});
}
现在创建一个类来简易实现
function _timeout(time) {
return new Promise((reslove, reject) => {
setTimeout(() => {
reslove();
}, time);
});
}
class SuperTask {
constructor(limit = 2) {
this.limit = limit; // 设置执行队列中允许同时执行任务的数量
this.taskQueue = []; // 用于存储的任务队列
this.executeNum = 0; // 执行队列中的任务数量
}
addTask(time, fn) {
// 往taskQueue中添加任务
this.add(() => _timeout(time)).then(() => {
fn();
});
}
add(fn) {
return new Promise((reslove, reject) => {
this.taskQueue.push({
fn,
reslove,
reject,
});
this._run();
});
}
_run() {
while (this.limit > this.executeNum && this.taskQueue.length > 0) {
const { fn, reslove, reject } = this.taskQueue.shift(); // 每次从taskQueue中取第一个排队任务
this.executeNum++;
fn().then(() => {
// 任务是一个promise
reslove();
this.executeNum--;
this._run();
});
}
}
}
const superTask = new SuperTask();
superTask.addTask(10000, () => {
console.log("任务1结束");
}); //10000ms输出,任务1结束
superTask.addTask(5000, () => {
console.log("任务2结束");
}); //5000ms输出,任务2结束
superTask.addTask(3000, () => {
console.log("任务3结束");
}); //8000ms输出,任务3结束
superTask.addTask(4000, () => {
console.log("任务4结束");
}); //12000ms输出,任务4结束
superTask.addTask(5000, () => {
console.log("任务5结束");
}); //15000ms输出,任务5结束