Improve application responsiveness and background processing
This commit is contained in:
+12
-5
@@ -1,25 +1,32 @@
|
||||
/** Poll visible page content without overlapping requests. Fleet watches use their own monitor. */
|
||||
export function pollVisible(task: () => void | Promise<unknown>, interval: number, immediate = true): () => void {
|
||||
export function pollVisible(task: (signal: AbortSignal) => unknown | Promise<unknown>, interval: number, immediate = true): () => void {
|
||||
let stopped = false;
|
||||
let running = false;
|
||||
let timer: ReturnType<typeof setTimeout> | undefined;
|
||||
let controller: AbortController | undefined;
|
||||
let failures = 0;
|
||||
const visible = () => document.visibilityState !== 'hidden';
|
||||
const run = async () => {
|
||||
if (stopped || running || !visible()) return;
|
||||
clearTimeout(timer);
|
||||
running = true;
|
||||
try { await task(); }
|
||||
catch (error) { console.error('Page refresh failed', error); }
|
||||
controller = new AbortController();
|
||||
const timeout = setTimeout(() => controller?.abort(), 30_000);
|
||||
try { failures = await task(controller.signal) === false ? failures + 1 : 0; }
|
||||
catch (error) { if (!controller.signal.aborted) { failures++; console.error('Page refresh failed', error); } }
|
||||
finally {
|
||||
clearTimeout(timeout);
|
||||
controller = undefined;
|
||||
running = false;
|
||||
if (!stopped && visible()) timer = setTimeout(run, interval);
|
||||
if (!stopped && visible()) timer = setTimeout(run, interval * Math.min(8, 2 ** failures));
|
||||
}
|
||||
};
|
||||
const visibility = () => {
|
||||
clearTimeout(timer);
|
||||
if (!visible()) controller?.abort();
|
||||
if (document.visibilityState !== 'hidden') void run();
|
||||
};
|
||||
document.addEventListener('visibilitychange', visibility);
|
||||
if (immediate) void run(); else timer = setTimeout(run, interval);
|
||||
return () => { stopped = true; clearTimeout(timer); document.removeEventListener('visibilitychange', visibility); };
|
||||
return () => { stopped = true; clearTimeout(timer); controller?.abort(); document.removeEventListener('visibilitychange', visibility); };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user