UNPKG

next-intl

Version:

Internationalization (i18n) for Next.js

86 lines (81 loc) 2.37 kB
/** * De-duplicates excessive save invocations, * while keeping a single one instant. */ class SaveScheduler { isSaving = false; pendingResolvers = []; constructor(delayMs = 50) { this.delayMs = delayMs; } async schedule(saveTask) { return new Promise((resolve, reject) => { this.pendingResolvers.push({ resolve, reject }); this.nextSaveTask = saveTask; if (!this.isSaving && !this.saveTimeout) { // Not currently saving and no scheduled save, save immediately this.executeSave(); } else if (this.saveTimeout) { // A save is already scheduled, reschedule to debounce this.scheduleSave(); } // If isSaving is true and no timeout is scheduled, the current save // will check for pending resolvers when it completes and schedule // another save if needed (see finally block in executeSave) }); } scheduleSave() { if (this.saveTimeout) { clearTimeout(this.saveTimeout); } this.saveTimeout = setTimeout(() => { this.saveTimeout = undefined; this.executeSave(); }, this.delayMs); } async executeSave() { if (this.isSaving) { return; } const saveTask = this.nextSaveTask; if (!saveTask) { return; } // Capture current pending resolvers for this save const resolversForThisSave = this.pendingResolvers; this.pendingResolvers = []; this.nextSaveTask = undefined; this.isSaving = true; try { const result = await saveTask(); // Resolve only the promises that were pending when this save started resolversForThisSave.forEach(({ resolve }) => resolve(result)); } catch (error) { // Reject only the promises that were pending when this save started resolversForThisSave.forEach(({ reject }) => reject(error)); } finally { this.isSaving = false; // If new saves were requested during this save, schedule another if (this.pendingResolvers.length > 0) { this.scheduleSave(); } } } [Symbol.dispose]() { if (this.saveTimeout) { clearTimeout(this.saveTimeout); this.saveTimeout = undefined; } this.pendingResolvers = []; this.nextSaveTask = undefined; this.isSaving = false; } } export { SaveScheduler as default };