设计一个异步队列-JS实现

330数据结构kohai

实现结果

// 创建一个队列实例
const queue = AsyncQueue.create();
// 定义一个睡眠函数
const sleep = (t) => new Promise((r) => setTimeout(r, t));

// 往队列中添加一个异步方法,方法内部睡眠了 1s,1s 后打印并返回结果,
// push 方法返回一个 promise 实例,值为异步方法的返回值。
queue.push(async () => {
  await sleep(1000);
  console.log('1s ', new Date());
  return [1, new Date()];
}).then(console.log);

// 添加的异步方法内部出现异常,也会通过 push 方法抛出来,
// 通过 catch 可以进行捕获,该异常只会终止当前任务,对后续的任务不会有影响。
queue.push(async () => {
  await sleep(1000);
  console.log('2s ', new Date());
  if (new Date().getFullYear() === 2021) {
    throw new Error('Current year is 2021');
  }
  return [2, new Date()];
}).then(console.log).catch(console.error);

queue.push(async () => {
  await sleep(1000);
  console.log('3s ', new Date());
  return [3, new Date()];
}).then(console.log);
js
复制代码

实现

class AsyncQueue {
  static create(name) {
    return new this(name);
  }

  constructor(name) {
    this.name = name;
    // 任务队列
    this.queue = [];
    // 是否有任务正常执行
    this.running = false;
  }

  push(fun) {
    return new Promise((resovle, reject) => {
      // 将 fun 包装一层放进任务队列中
      this.queue.push(async () => {
        this.running = true;
        try {
          const res = await fun();
          resovle(res);
        } catch(e) {
          reject(e);
        }
        
        this.running = false;
        // 获取下一个任务并执行
        const next = this.queue.shift();
        next?.();
      });
      // 若当前未有任务执行中,则触发队列的执行
      if (!this.running) {
        this.queue.shift()?.();
      }
    });
  }
}
js
复制代码
编辑于:2021-10-01 15:25:18