Spaces:
Runtime error
Runtime error
Download frontend/src/hooks/usePoll.ts from firebird-technologies/NoteStack-Test: direct link, hf CLI and curl.
- Browser
- Download file 2.27 kB
-
https://huggingface.co/spaces/firebird-technologies/NoteStack-Test/resolve/main/frontend/src/hooks/usePoll.ts
- Command line
-
hf download hf://spaces/firebird-technologies/NoteStack-Test/frontend/src/hooks/usePoll.ts
-
curl -L -o usePoll.ts https://huggingface.co/spaces/firebird-technologies/NoteStack-Test/resolve/main/frontend/src/hooks/usePoll.ts
2.27 kB
| import { useEffect, useRef, useState } from "react"; | |
| /** | |
| * Calls `fn` every `intervalMs` until `until(result)` is true. Calls never overlap (each waits for the last), | |
| * it pauses while the tab is hidden, and it backs off after errors. Change `key` to restart it. | |
| * | |
| * `data`, `error` and `done` belong to the run (the `key`) that produced them: a new key or turning polling off reads | |
| * as a fresh start in the same render. Otherwise a caller's "finished?" check would still see the previous run's | |
| * `done` the moment a new run begins, and end it at once. | |
| */ | |
| export function usePoll<T>( | |
| fn: (() => Promise<T>) | null, | |
| { intervalMs, until, key }: { intervalMs: number; until: (t: T) => boolean; key?: unknown }, | |
| ): { data: T | null; error: unknown; done: boolean } { | |
| const [result, setResult] = useState<{ key: unknown; data: T | null; error: unknown; done: boolean } | null>(null); | |
| const fnRef = useRef(fn); | |
| const untilRef = useRef(until); | |
| fnRef.current = fn; | |
| untilRef.current = until; | |
| const enabled = fn !== null; | |
| useEffect(() => { | |
| if (!enabled) return; | |
| const runKey = key; | |
| let stopped = false; | |
| let timer: ReturnType<typeof setTimeout> | undefined; | |
| let failures = 0; | |
| setResult(null); // a re-enabled run with the same key starts clean too | |
| const tick = async () => { | |
| if (stopped) return; | |
| if (document.hidden) { | |
| timer = setTimeout(tick, intervalMs); | |
| return; | |
| } | |
| try { | |
| const next = await fnRef.current!(); | |
| if (stopped) return; | |
| failures = 0; | |
| const done = untilRef.current(next); | |
| setResult({ key: runKey, data: next, error: null, done }); | |
| if (done) return; | |
| } catch (e) { | |
| if (stopped) return; | |
| failures += 1; | |
| setResult((r) => ({ key: runKey, data: r !== null && r.key === runKey ? r.data : null, error: e, done: false })); | |
| } | |
| timer = setTimeout(tick, intervalMs * Math.min(2 ** failures, 8)); | |
| }; | |
| tick(); | |
| return () => { | |
| stopped = true; | |
| clearTimeout(timer); | |
| }; | |
| }, [enabled, intervalMs, key]); | |
| const mine = enabled && result !== null && result.key === key ? result : null; | |
| return { data: mine?.data ?? null, error: mine?.error ?? null, done: mine?.done ?? false }; | |
| } | |