Реализация асинхронно итерируемой очереди для JavaScript

Во время учебы Дено который представляет собой своего рода Node со всем, нормализованным для современных JS и TS, я быстро встретил;

import { serve } from "https://deno.land/std@0.87.0/http/server.ts";

const server = serve({ hostname: "0.0.0.0", port: 8080 });

for await (const request of server) {
  request.respond({ status: 200, body: "Whatever" });
}

Здесь server объект асинхронный итератор. Всякий раз, когда поступает запрос, он включает for await of цикл один раз. Я считаю server должен быть создан из типа Asynchronously Iterable Queue.

Поэтому я попытался реализовать аналогичную асинхронную очередь поверх лучшего синхронного типа очереди в JS, о котором я знаю.

Очевидно, что в AsyncQueue мы не можем иметь .dequeue() или же .peek() функций, поскольку в этом случае удаление из очереди происходит автоматически при разрешении первого обещания, и нет смысла смотреть на первое обещание в очереди обещаний. Вместо этого у нас есть .next() функция для удаления из очереди вместе с .enqueue() функция для вставки новых обещаний.

Важный аспект этого AsyncQueue заключается в том, что он должен иметь возможность принимать новые обещания как синхронно, так и асинхронно, что означает, что он будет работать вечно.

Итак, код приведен ниже, и я хотел бы знать, можно ли его еще больше упростить, или, возможно, есть вещи для повышения производительности или еще много чего. Пожалуйста, не забывайте о моем стиле отступов, так как я не буду его менять. Также мне нравится использовать Поля частного класса очень.

class AsyncQueue {

  #HEAD;
  #LAST;

  static #LINK = class {
    #RESOLVER;

    constructor(promise,resolver){
      this.promise = new Promise(resolve => ( this.#RESOLVER = resolve
                                            , promise.then(value => resolver({value, done: false}))
                                            ));
      this.next    = void 0;
    }

    get resolver(){
      return this.#RESOLVER;
    }
  }

  constructor(){
    new Promise(resolve => this.#HEAD = new AsyncQueue.#LINK(Promise.resolve(null),resolve));
  };

  enqueue(promise){
    this.#LAST = this.#LAST ? this.#LAST.next = new AsyncQueue.#LINK(promise,this.#LAST.resolver)
                            : this.#HEAD      = new AsyncQueue.#LINK(promise,this.#HEAD.resolver)
  }

  next(){
    var promise = this.#HEAD.promise.then(value => ({value, done: false}));
    this.#HEAD.next ? this.#HEAD = this.#HEAD.next
                    : this.#LAST = void 0;
    return promise;
  };

  [Symbol.asyncIterator]() {
    return this;
  };
};


var aq = new AsyncQueue();

async function getAsyncValues(){
  for await (let item of aq){
    console.log(`The Promise resolved with a value of ${item.value}`);
  };
};


getAsyncValues();
// synchronous insertion of promises
for (var i=1; i <= 5; i++) aq.enqueue(new Promise(resolve => setTimeout(resolve, 1000*i, `done at ${1000*i}ms`)));
// asynchronous insertion od a promise
setTimeout(aq.enqueue.bind(aq),7500,Promise.resolve("this is an asynchronnous insertion"));

0

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *