Files
i-want-to-heal-mmo/src/platform/rateLimitedPublisher.ts
T
2026-07-10 23:47:37 -04:00

51 lines
1.2 KiB
TypeScript

export interface RateLimitedPublisher {
request: () => void;
cancel: () => void;
dispose: () => void;
}
/**
* Coalesces bursty state updates while preserving an immediate leading publish.
* The trailing publish always contains current state because `publish` reads it
* when the timer fires.
*/
export function createRateLimitedPublisher(
publish: () => void,
intervalMs: number,
now: () => number = () => performance.now(),
): RateLimitedPublisher {
let lastPublishedAt = Number.NEGATIVE_INFINITY;
let timer: ReturnType<typeof setTimeout> | null = null;
let disposed = false;
const run = () => {
timer = null;
if (disposed) return;
lastPublishedAt = now();
publish();
};
const cancel = () => {
if (timer !== null) clearTimeout(timer);
timer = null;
};
return {
request: () => {
if (disposed) return;
const remaining = intervalMs - (now() - lastPublishedAt);
if (remaining <= 0) {
if (timer !== null) clearTimeout(timer);
run();
return;
}
if (timer === null) timer = setTimeout(run, remaining);
},
cancel,
dispose: () => {
disposed = true;
cancel();
},
};
}