mirror of
https://github.com/olehomelchenko/astrolabe.git
synced 2026-08-08 02:02:33 +00:00
Docs: trim arch 05 debounced-renderer sketch to its generation-guard insight
This commit is contained in:
@@ -384,49 +384,23 @@ export interface DebouncedRenderer {
|
||||
cancel(): void;
|
||||
}
|
||||
|
||||
export function createDebouncedRenderer(opts: {
|
||||
/** Current debounce delay in ms; read fresh each schedule so settings apply live. */
|
||||
delayMs: () => number;
|
||||
/** Performs one render. Reads the current spec/theme; awaits the embed. */
|
||||
render: () => Promise<void>;
|
||||
/** Toggle the non-blocking busy indicator. */
|
||||
setBusy: (busy: boolean) => void;
|
||||
}): DebouncedRenderer {
|
||||
let timer: ReturnType<typeof setTimeout> | null = null;
|
||||
let generation = 0; // guards against a stale in-flight render finishing late
|
||||
|
||||
// The factory wires the three operations over one timer. schedule() does
|
||||
// `setTimeout(run, delayMs())`, clearing any pending timer first (delayMs read fresh
|
||||
// so a settings change applies live); flush() clears the timer and runs now; cancel()
|
||||
// clears it and bumps `generation`. The non-obvious part is out-of-order protection:
|
||||
function createDebouncedRenderer(opts): DebouncedRenderer {
|
||||
let generation = 0;
|
||||
const run = async () => {
|
||||
timer = null;
|
||||
const mine = ++generation;
|
||||
const mine = ++generation; // capture this render's turn
|
||||
opts.setBusy(true);
|
||||
try {
|
||||
await opts.render();
|
||||
} finally {
|
||||
// Only the most recent render clears the indicator.
|
||||
if (mine === generation) opts.setBusy(false);
|
||||
if (mine === generation) opts.setBusy(false); // only the latest render clears it
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
schedule() {
|
||||
if (timer) clearTimeout(timer); // cancel the pending render
|
||||
timer = setTimeout(run, opts.delayMs());
|
||||
},
|
||||
flush() {
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
timer = null;
|
||||
}
|
||||
void run();
|
||||
},
|
||||
cancel() {
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
timer = null;
|
||||
}
|
||||
generation++; // abandon any in-flight result
|
||||
},
|
||||
};
|
||||
// …schedule/flush/cancel as above. A slow render that resolves after a newer one
|
||||
// fails the `mine === generation` check, so it can't clobber the fresh view/indicator.
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user