refactor: prevent rapid polling calls from making multiple polling timers
import { useCallback, useEffect, useRef } from 'react';
-import { isAsyncFunction } from 'utils/data';
-
const DEFAULT_DELAY = 5000;
type PollingFn = (() => Promise<void>) | (() => void);
interface PollingOptions {
delay?: number;
- triggers?: unknown[];
}
-const usePolling =
- (pollingFn: PollingFn, { delay }: PollingOptions = {}): (() => void) => {
+const usePolling = (pollingFn: PollingFn, { delay }: PollingOptions = {}): (() => void) => {
const timerId = useRef<NodeJS.Timeout>();
- const countId = useRef(0);
-
- const pollingRoutine = useCallback(async (): Promise<void> => {
- countId.current++;
- isAsyncFunction(pollingFn) ? await pollingFn() : pollingFn();
- timerId.current = setTimeout(() => {
- pollingRoutine();
- }, delay || DEFAULT_DELAY);
- }, [ pollingFn, delay ]);
const stopPolling = useCallback((): void => {
if (timerId.current) {
@@ -31,8 +18,15 @@ const usePolling =
}
}, []);
+ const pollingRoutine = useCallback(async (): Promise<void> => {
+ await pollingFn();
+
+ if (timerId.current) clearTimeout(timerId.current);
+
+ timerId.current = setTimeout(() => pollingRoutine(), delay || DEFAULT_DELAY);
+ }, [ pollingFn, delay ]);
+
useEffect(() => {
- stopPolling();
pollingRoutine();
return stopPolling;
}, [ pollingRoutine, stopPolling ]);
