javascript - 如何在JS/TS中实现伪阻塞异步队列?

标签 javascript typescript asynchronous promise async-await

所以这是一个矛盾的说法:我想在 javascript/typescript 中创建一个异步阻塞队列(如果你可以在没有 typescript 的情况下实现它,那很好)。基本上,我想实现类似 Java 的 BlockingQueue expect 的东西,而不是实际阻塞,它会是异步的,我可以等待出队。

这是我要实现的接口(interface):

interface AsyncBlockingQueue<T> {
  enqueue(t: T): void;
  dequeue(): Promise<T>;
}

我会这样使用它:

// enqueue stuff somewhere else

async function useBlockingQueue() {
  // as soon as something is enqueued, the promise will be resolved:
  const value = await asyncBlockingQueue.dequeue();
  // this will cause it to await for a second value
  const secondValue = await asyncBlockingQueue.dequeue();
}

有什么想法吗?

最佳答案

其实很简单,dequeue 会创建一个 promise,enqueue 会 resolve。我们只需要将解析器保持在队列中 - 并且还要关心值在出队之前入队的情况,将已经完成的 promise 保持在队列中。

class AsyncBlockingQueue {
  constructor() {
    // invariant: at least one of the arrays is empty
    this.resolvers = [];
    this.promises = [];
  }
  _add() {
    this.promises.push(new Promise(resolve => {
      this.resolvers.push(resolve);
    }));
  }
  enqueue(t) {
    // if (this.resolvers.length) this.resolvers.shift()(t);
    // else this.promises.push(Promise.resolve(t));
    if (!this.resolvers.length) this._add();
    this.resolvers.shift()(t);
  }
  dequeue() {
    if (!this.promises.length) this._add();
    return this.promises.shift();
  }
  // now some utilities:
  isEmpty() { // there are no values available
    return !this.promises.length; // this.length <= 0
  }
  isBlocked() { // it's waiting for values
    return !!this.resolvers.length; // this.length < 0
  }
  get length() {
    return this.promises.length - this.resolvers.length;
  }
  [Symbol.asyncIterator]() {
    // Todo: Use AsyncIterator.from()
    return {
      next: () => this.dequeue().then(value => ({done: false, value})),
      [Symbol.asyncIterator]() { return this; },
    };
  }
}

我不了解 TypeScript,但想必添加必要的类型注释很简单。

为了获得更好的性能,请使用带有循环缓冲区的队列实现而不是普通数组,例如this one .您也可以只使用一个队列,并记住您当前存储的是 promise 还是解析器。

关于javascript - 如何在JS/TS中实现伪阻塞异步队列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47157428/

相关文章:

javascript - nodejs : Async.系列只执行第一个函数就停止了

mongodb - 将数据传递给服务时在 Controller 中验证 DTO

javascript - 空值不会以 Angular 4 形式提交

ios - swift shouldPerformSegueWithIdentifier 异步获取数据

iphone - 在 iPhone 上发布到服务器的最简单方法?我不在乎回应

javascript - jQuery Knob,仅在上次更改/发布时提交

javascript - Disqus 如何知道我是我假装的网站?

javascript - javascript 有没有办法检查 gif 在页面上循环了多少次?

typescript - 闭包编译器 + typescript

angular - 没有 detectChanges 测试可观察对象失败