UNPKG

@seriousme/opifex

Version:

MQTT client & server for Deno & NodeJS

76 lines (69 loc) 1.68 kB
import { nextTick } from "./nextTick.ts"; /** * An Async Queue is a queue that can be used to push items to it and then wait * for them to be consumed. * * @example * ```ts * const queue = new AsyncQueue<string>(); * queue.push("hello"); * for await (const item of queue) { * console.log(item); // "hello" * } * ``` */ export class AsyncQueue<T> { private queue: T[] = []; private maxQueueLength = Infinity; private nextResolve = (_value: T) => {}; private nextReject = (_reason?: string) => {}; private done = false; private hasNext = false; constructor(maxQueueLength?: number) { if (maxQueueLength) { this.maxQueueLength = maxQueueLength; } } async next(): Promise<T> { await nextTick(); if (this.done && this.queue.length === 0) { return Promise.reject("Closed"); } return new Promise((resolve, reject) => { if (this.queue.length > 0) { const item = this.queue.shift(); if (item) { return resolve(item); } } this.nextResolve = resolve; this.nextReject = reject; this.hasNext = true; }); } close(reason = "closed"): void { this.done = true; if (this.hasNext) { this.nextReject(reason); } } async *[Symbol.asyncIterator](): AsyncGenerator<Awaited<T>, void, unknown> { while (true) { yield this.next(); } } push(item: T) { if (this.hasNext) { this.nextResolve(item); this.hasNext = false; return; } if (this.queue.length > this.maxQueueLength) { this.queue.shift(); } this.queue.push(item); } get isDone(): boolean { return this.done; } }