UNPKG

zwave-js

Version:

Z-Wave driver written entirely in JavaScript/TypeScript

93 lines 3.16 kB
import { createDeferredPromise, } from "alcalzone-shared/deferred-promise"; import { SortedList } from "alcalzone-shared/sorted-list"; /** * The transaction queue offers an async-iterable interface to a list of transactions. */ export class TransactionQueue { constructor(options) { this.name = options?.name ?? "unnamed"; this.mayStartNextTransaction = options?.mayStartNextTransaction ?? (() => true); } name; mayStartNextTransaction; transactions = new SortedList(); currentTransaction; add(...items) { this.transactions.add(...items); this.trigger(); } remove(...items) { this.transactions.remove(...items); this.trigger(); } find(predicate) { return this.transactions.find(predicate); } finalizeTransaction() { this.currentTransaction = undefined; } get length() { return this.transactions.length; } /** Causes the queue to re-evaluate whether the next transaction may be started */ trigger() { while (this.transactions.length > 0 && this.listeners.length > 0) { if (this.mayStartNextTransaction(this.transactions.peekStart())) { const promise = this.listeners.shift(); const item = this.transactions.shift(); this.currentTransaction = item; promise.resolve(item); } else { break; } } } // A list of Promises that are waiting to be resolved listeners = []; // Whether the queue was ended ended = false; /** Ends the queue after it has been drained */ end() { this.ended = true; } /** Ends the queue and discards all pending items */ abort() { this.ended = true; this.transactions.clear(); this.currentTransaction = undefined; for (const p of this.listeners) { p.resolve(undefined); } } // Enable iterating the queue using for-await-of [Symbol.asyncIterator]() { return { next: async () => { let value; if (this.transactions.length > 0 && this.mayStartNextTransaction(this.transactions.peekStart())) { // If the next transaction may be started, return it value = this.transactions.shift(); } else if (!this.ended) { // Otherwise create a new promise and add it to the pending list const promise = createDeferredPromise(); this.listeners.push(promise); value = await promise; } this.currentTransaction = value; if (value) { // We have a value, return it return { value, done: false }; } else { // No value means the queue was ended return { value: undefined, done: true }; } }, }; } } //# sourceMappingURL=Queue.js.map