Во время учебы Дено который представляет собой своего рода 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"));