UNPKG

@nostr-dev-kit/ndk

Version:

NDK - Nostr Development Kit

90 lines (75 loc) 2.36 kB
type QueueItem<T> = { /** * Deterministic id of the item */ id: string; /** * A function to process the item * @returns */ func: () => Promise<T>; }; export class Queue<T> { private queue: QueueItem<T>[] = []; private maxConcurrency: number; private processing: Set<string> = new Set(); private promises: Map<string, Promise<T>> = new Map(); constructor(_name: string, maxConcurrency: number) { this.maxConcurrency = maxConcurrency; } public add(item: QueueItem<T>): Promise<T> { if (this.promises.has(item.id)) { return this.promises.get(item.id)!; } const promise = new Promise<T>((resolve, reject) => { this.queue.push({ ...item, func: () => item.func().then( (result) => { resolve(result); return result; // Return the result to match the expected type. }, (error) => { reject(error); // It's important to rethrow the error here to not accidentally resolve the promise. // However, since TypeScript 4.4, you can set "useUnknownInCatchVariables" to false if this line errors. throw error; } ), }); this.process(); }); this.promises.set(item.id, promise); promise.finally(() => { this.promises.delete(item.id); this.processing.delete(item.id); this.process(); }); return promise; } private process() { if (this.processing.size >= this.maxConcurrency || this.queue.length === 0) { return; } const item = this.queue.shift(); if (!item || this.processing.has(item.id)) { return; } this.processing.add(item.id); item.func(); } public clear() { this.queue = []; } public clearProcessing() { this.processing.clear(); } public clearAll() { this.clear(); this.clearProcessing(); } public length() { return this.queue.length; } }