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]);
}
|