import shim from './shim'; export interface QueueItemAction { (): void; } export interface QueueItem { action: QueueItemAction; // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied context: any; } export enum IntervalType { Debounce = 1, Fixed = 2, } // The AsyncActionQueue can be used to debounce asynchronous actions, to make sure // they run in the right order, and also to ensure that if multiple actions are emitted // only the last one is executed. This is particularly useful to save data in the background. // Each queue should be associated with a specific entity (a note, resource, etc.) export default class AsyncActionQueue { private queue_: QueueItem[] = []; private interval_: number; private intervalType_: number; // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied private scheduleProcessingIID_: any = null; private processing_ = false; private processingFinishedPromise_: Promise; private onProcessingFinished_: ()=> void; public constructor(interval = 100, intervalType: IntervalType = IntervalType.Debounce) { this.interval_ = interval; this.intervalType_ = intervalType; this.resetFinishProcessingPromise_(); } private resetFinishProcessingPromise_() { this.processingFinishedPromise_ = new Promise(resolve => { this.onProcessingFinished_ = resolve; }); } // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied public push(action: QueueItemAction, context: any = null) { this.queue_.push({ action: action, context: context, }); this.scheduleProcessing(); } public get isEmpty(): boolean { return !this.queue_.length; } private scheduleProcessing(interval: number = null) { if (interval === null) interval = this.interval_; if (this.scheduleProcessingIID_) { if (this.intervalType_ === IntervalType.Fixed) return; shim.clearTimeout(this.scheduleProcessingIID_); } this.scheduleProcessingIID_ = shim.setTimeout(() => { this.scheduleProcessingIID_ = null; void this.processQueue(); }, interval); } private async processQueue() { if (this.processing_) { this.scheduleProcessing(); return; } this.processing_ = true; const itemCount = this.queue_.length; if (itemCount) { const item = this.queue_[itemCount - 1]; await item.action(); this.queue_.splice(0, itemCount); } this.processing_ = false; if (this.queue_.length === 0) { this.onProcessingFinished_(); this.resetFinishProcessingPromise_(); } } public async reset() { if (this.scheduleProcessingIID_) { shim.clearTimeout(this.scheduleProcessingIID_); this.scheduleProcessingIID_ = null; } this.queue_ = []; return this.processAllNow(); } public async processAllNow() { this.scheduleProcessing(1); return this.waitForAllDone(); } public async waitForAllDone() { if (!this.queue_.length) return Promise.resolve(); return this.processingFinishedPromise_; } }