How to implement a pseudo blocking async queue in JS/TS?

后端 未结 2 831
野趣味
野趣味 2020-11-29 12:30

So here\'s an oxymoron: I want to create an asynchronous blocking queue in javascript/typescript (if you can implement it without typescript, that\'s fine). Basically I want

2条回答
  •  遥遥无期
    2020-11-29 13:16

    It's quite simple actually, dequeue will create a promise that enqueue will resolve. We just have to keep the resolvers in a queue - and also care about the case where values are enqueued before they are dequeued, keeping the already fulfilled promises in a queue.

    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]() {
        return {
          next: () => this.dequeue().then(value => ({done: false, value}))
        };
      }
    }
    

    I don't know TypeScript, but presumably it's simple to add the the necessary type annotations.

    For better performance, use a Queue implementation with circular buffers instead of plain arrays, e.g. this one. You might also use only a single queue and remember whether you currently store promises or resolvers.

提交回复
热议问题