Files
klz-cables.com/.pnpm-store/v10/files/d3/ab2549341e2f5a9e2170a39cbbbab40ba3fc3ce546d9e37c123792018b6e4ff9f882993adedae66d4b1421a12126efbae7fb67dca3beafe19bcf8177c1ade9
Marc Mintel 5397309103
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 20s
Build & Deploy / 🧪 QA (push) Failing after 34s
Build & Deploy / 🏗️ Build (push) Has started running
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Smoke Test (push) Has been cancelled
Build & Deploy / ⚡ Lighthouse (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
fix(products): fix breadcrumbs and product filtering (backport from main)
2026-02-24 16:04:21 +01:00

86 lines
2.3 KiB
Plaintext

/**
* 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 };