UNPKG

@tanstack/query-core

Version:

The framework agnostic core that powers TanStack Query

165 lines (164 loc) • 5.97 kB
//#region src/timeoutManager.ts const defaultTimeoutProvider = { setTimeout: (callback, delay) => setTimeout(callback, delay), clearTimeout: (timeoutId) => clearTimeout(timeoutId), setInterval: (callback, delay) => setInterval(callback, delay), clearInterval: (intervalId) => clearInterval(intervalId) }; /** * Allows customization of how timeouts are created. * * `@tanstack/query-core` makes liberal use of timeouts to implement `staleTime` * and `gcTime`. The default TimeoutManager provider uses the platform's global * `setTimeout` implementation, which is known to have scalability issues with * thousands of timeouts on the event loop. * * If you hit this limitation, consider providing a custom TimeoutProvider that * coalesces timeouts. */ var TimeoutManager = class { #provider = defaultTimeoutProvider; #providerCalled = false; /** * `setTimeoutProvider` can be used to set a custom implementation of the * `setTimeout`, `clearTimeout`, `setInterval`, `clearInterval` functions, * called a `TimeoutProvider`. * * This may be useful if you notice event loop performance issues with * thousands of queries. A custom TimeoutProvider could also support timer * delays longer than the global `setTimeout` maximum delay value of about * 24 days. * * It is important to call `setTimeoutProvider` before creating a * QueryClient or queries, so that the same provider is used consistently * for all timers in the application, since different TimeoutProviders * cannot cancel each others' timers. * @param provider - The `TimeoutProvider` to use for all timers from now on. * @example * ```ts * import { timeoutManager, QueryClient } from '@tanstack/query-core' * import { CustomTimeoutProvider } from './CustomTimeoutProvider' * * timeoutManager.setTimeoutProvider(new CustomTimeoutProvider()) * * export const queryClient = new QueryClient() * ``` */ setTimeoutProvider(provider) { if (process.env.NODE_ENV !== "production") { if (this.#providerCalled && provider !== this.#provider) console.error(`[timeoutManager]: Switching provider after calls to previous provider might result in unexpected behavior.`, { previous: this.#provider, provider }); } this.#provider = provider; if (process.env.NODE_ENV !== "production") this.#providerCalled = false; } /** * `setTimeout` schedules a callback to run after approximately `delay` * milliseconds, like the global `setTimeout` function. The callback can be * canceled with `clearTimeout`. * * It returns a timer ID, which may be a number or an object that can be * coerced to a number via `Symbol.toPrimitive`. * @param callback - The function to call when the timeout elapses. * @param delay - The time to wait before calling `callback`, in milliseconds. * @returns The timer ID, to pass to {@link TimeoutManager#clearTimeout}. * @example * ```ts * import { timeoutManager } from '@tanstack/query-core' * * const timeoutId = timeoutManager.setTimeout( * () => console.log('ran at:', new Date()), * 1000, * ) * * const timeoutIdNumber: number = Number(timeoutId) * ``` */ setTimeout(callback, delay) { if (process.env.NODE_ENV !== "production") this.#providerCalled = true; return this.#provider.setTimeout(callback, delay); } /** * `clearTimeout` cancels a timeout callback scheduled with `setTimeout`, * like the global `clearTimeout` function. It should be called with a * timer ID returned by `setTimeout`. * @param timeoutId - The timer ID returned by `setTimeout`, or `undefined`. * @example * ```ts * import { timeoutManager } from '@tanstack/query-core' * * const timeoutId = timeoutManager.setTimeout( * () => console.log('ran at:', new Date()), * 1000, * ) * * timeoutManager.clearTimeout(timeoutId) * ``` */ clearTimeout(timeoutId) { this.#provider.clearTimeout(timeoutId); } /** * `setInterval` schedules a callback to be called approximately every * `delay` milliseconds, like the global `setInterval` function. * * Like `setTimeout`, it returns a timer ID, which may be a number or an * object that can be coerced to a number via `Symbol.toPrimitive`. * @param callback - The function to call on every interval. * @param delay - The time between calls, in milliseconds. * @returns The timer ID, to pass to {@link TimeoutManager#clearInterval}. * @example * ```ts * import { timeoutManager } from '@tanstack/query-core' * * const intervalId = timeoutManager.setInterval( * () => console.log('ran at:', new Date()), * 1000, * ) * ``` */ setInterval(callback, delay) { if (process.env.NODE_ENV !== "production") this.#providerCalled = true; return this.#provider.setInterval(callback, delay); } /** * `clearInterval` can be used to cancel an interval, like the global * `clearInterval` function. It should be called with an interval ID * returned by `setInterval`. * @param intervalId - The timer ID returned by `setInterval`, or `undefined`. * @example * ```ts * import { timeoutManager } from '@tanstack/query-core' * * const intervalId = timeoutManager.setInterval( * () => console.log('ran at:', new Date()), * 1000, * ) * * timeoutManager.clearInterval(intervalId) * ``` */ clearInterval(intervalId) { this.#provider.clearInterval(intervalId); } }; /** * Singleton instance of {@link TimeoutManager}, used throughout TanStack Query to schedule and cancel timers. */ const timeoutManager = new TimeoutManager(); /** * In many cases code wants to delay to the next event loop tick; this is not * mediated by {@link timeoutManager}. * * This function is provided to make auditing the `tanstack/query-core` for * incorrect use of system `setTimeout` easier. * @param callback - The function to call on the next event loop tick. */ function systemSetTimeoutZero(callback) { setTimeout(callback, 0); } //#endregion export { TimeoutManager, defaultTimeoutProvider, systemSetTimeoutZero, timeoutManager }; //# sourceMappingURL=timeoutManager.js.map