UNPKG

@daiso-tech/core

Version:

The library offers flexible, framework-agnostic solutions for modern web applications, built on adaptable components that integrate seamlessly with popular frameworks like Next Js.

107 lines 3.03 kB
/** * @module Async */ import {} from "../../../utilities/_module-exports.js"; import { LazyPromise } from "../../../async/utilities/_module.js"; import { v4 } from "uuid"; import { CapacityFullAsyncError } from "../../../async/async.errors.js"; /** * @internal */ class Queue { array = []; size() { return this.array.length; } enqueue(value) { this.array.push(value); } dequeue() { return this.array.shift() ?? null; } } /** * @internal */ export class PromiseQueue { settings; queue = new Queue(); listeners = new Map(); constructor(settings) { this.settings = settings; // eslint-disable-next-line @typescript-eslint/no-floating-promises this.start(); } async start() { // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition, no-constant-condition while (true) { await Promise.all(this.getItems().map((item) => this.process(item))); await LazyPromise.delay(this.settings.interval); } } getItems() { const values = []; for (let i = 0; i < this.settings.maxConcurrency; i++) { const item = this.queue.dequeue(); if (item === null) { continue; } values.push(item); } return values; } async process(item) { const listener = this.listeners.get(item.id); try { if (item.signal.aborted) { listener?.([null, item.signal.reason]); return; } const value = await item.func(item.signal); listener?.([value, null]); } catch (error) { listener?.([null, error]); throw error; } } enqueue(func, signal) { const id = v4(); if (this.settings.maxCapacity === null) { this.queue.enqueue({ id, func, signal, }); } else if (this.queue.size() <= this.settings.maxCapacity) { this.queue.enqueue({ id, func, signal }); } else { throw new CapacityFullAsyncError(`Max capacity reached, ${String(this.settings.maxCapacity)} items allowed.`); } return id; } listenOnce(id, listener) { this.listeners.set(id, listener); } asPromise(id) { return new Promise((resolve, reject) => { this.listenOnce(id, ([value, error]) => { if (value === null) { // eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors reject(error); return; } resolve(value); }); }); } /** * @throws {CapacityFullAsyncError} {@link CapacityFullAsyncError} */ add(func, signal) { return this.asPromise(this.enqueue(func, signal)); } } //# sourceMappingURL=promise-queue.js.map