Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | 18x 18x 18x 18x 45x 45x 45x 42x 42x 3x 45x 45x 44x 18x 18x 18x 18x | import { useEffect } from "react"; import { defaultPollingOptions } from "./defaultPollingOptions"; import { PollingOptions } from "./PollingOptions"; /** * This performs polling while a predicate returns true. * @param predicate - an async function that if false will skip the callback, but will still poll. * @param asyncFunction - the async function to call. * @param options - extra options for polling */ export function usePollingIf<T = unknown>( predicate: () => boolean | PromiseLike<boolean>, asyncFunction: () => T | PromiseLike<T>, options: Partial<PollingOptions> = {} ): void { const { intervalMs, immediate, onError } = { ...defaultPollingOptions, ...options, }; useEffect(() => { let timeoutID: ReturnType<typeof setTimeout>; /* * Flag to indicate that the async function is still actively running. If it is actively running it skips * execution and delays it until the next tick. */ let active = false; /* * Flag to indicate that the cleanup was invoked so no more executions should be performed. */ let cleanupCalled = false; // the function is built here rather than on the top level so the timeout variable is managed within this function. async function wrappedAsyncFunction(): Promise<void> { Eif (!active && !cleanupCalled) { active = true; if (await predicate()) { try { await asyncFunction(); } catch (e) { onError(e); } } active = false; } if (!cleanupCalled) { timeoutID = setTimeout(wrappedAsyncFunction, active ? 0 : intervalMs); } } timeoutID = setTimeout(wrappedAsyncFunction, immediate ? 0 : intervalMs); return () => { clearTimeout(timeoutID); cleanupCalled = true; }; }, [immediate, intervalMs, asyncFunction, onError, predicate]); } |