异步线程池
开发中我们会遇到这么一个场景,需要维护一个请求队列,一次只能请求2个或者多个接口,而且当一个请求结束后,就会进入队列,直到请求发送完毕。
- 如下有一个样例
addTask(10000, 1); // 10s 后 输出 1执行完毕
addTask(5000, 2); // 5s 后 2执行完毕
addTask(3000, 3); // 8s 后 3执行完毕
addTask(4000, 4); //12s 后 4执行完毕
addTask(5000, 5); // 15s 后 5执行完毕
下面我们来模拟一下
// 1. 显示模拟请求实现
const timeOut = (time) => {
return new Promise((resolve) => {
setTimeout(resolve, time);
});
};
// 3. 实现类
class TaskPool {
// 默认线程池大小为2
constructor(taskPoolLength = 2) {
// 线程池大小长度确定
this.taskPoolLength = taskPoolLength;
// 记录当前线程池中的任务
this.currentTaskLength = 0;
// 初始化线程池
this.tasks = [];
}
// 添加任务 传入 promise 任务
addTask(task) {
// 返回promise
return new Promise((resolve, reject) => {
// 因为执行函数需要调用resolve 和 reject 这个时候可以把resolve push进task进行绑定
this.tasks.push({
task,
resolve,
reject
});
// 执行函数
this._run();
})
}
_run() {
// 通过while 条件来判断 tasks 是否有任务,并且确定任务数量小于线程池大小
while(this.tasks.length && this.currentTaskLength < this.taskPoolLength) {
// 当前线程池任务++
this.currentTaskLength++;
const {task, resolve, reject} = this.tasks.shift()
task().then(resolve, reject).finally(() => {
// 执行完毕后 当前线程池任务--
this.currentTaskLength--;
// 递归调用
this._run();
});
}
}
}
// 2. 实现 addTask(time, value)
const taskPool = new TaskPool();
const addTask = (time, value) =>{
taskPool.addTask(() => timeOut(time)).then(() => {
console.log(`${value}执行完毕!`)
})
}
addTask(10000, 1); // 10s 后 输出 1执行完毕
addTask(5000, 2); // 5s 后 2执行完毕
addTask(3000, 3); // 8s 后 3执行完毕
addTask(4000, 4); //12s 后 4执行完毕
addTask(5000, 5); // 15s 后 5执行完毕