实现一个异步队列来实现一个队列池

文章展示了如何使用JavaScript创建一个简单的线程池,用于限制并发执行的异步任务数量。通过维护一个任务队列和控制执行中的任务数,确保每次只有指定数量的任务在运行,其余任务等待。这种机制有助于管理并发请求,避免服务器过载。

异步线程池

开发中我们会遇到这么一个场景,需要维护一个请求队列,一次只能请求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执行完毕

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值