mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 12:32:43 +00:00
The mood and dashboard prefetches and the sign-in location lookup raced their work against a bare setTimeout that was never cleared, leaving one live timer behind per render or sign-in after the work had already answered. A shared helper races the work and clears the timer.
25 lines
812 B
TypeScript
25 lines
812 B
TypeScript
/**
|
|
* Wait for `work` at most `ms`, then settle with `fallback` instead.
|
|
*
|
|
* The budget timer is cleared as soon as either side settles. A bare
|
|
* `Promise.race` against a `setTimeout` left the timer running after the
|
|
* work had long answered: one live timer per server render or per audited
|
|
* sign-in, each holding its closure until it fired. `work` is not
|
|
* cancelled; a rejection of `work` inside the budget rejects here too.
|
|
*/
|
|
export async function settleWithin<T, F>(
|
|
work: Promise<T>,
|
|
ms: number,
|
|
fallback: F,
|
|
): Promise<T | F> {
|
|
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
const budget = new Promise<F>((resolve) => {
|
|
timer = setTimeout(() => resolve(fallback), ms);
|
|
});
|
|
try {
|
|
return await Promise.race([work, budget]);
|
|
} finally {
|
|
clearTimeout(timer);
|
|
}
|
|
}
|