TimeoutManager purpose and uses
TimeoutManager handles setTimeout and setInterval timers in TanStack Query. It is used to implement features like query staleTime and gcTime, as well as retries, throttling, and debouncing. By default it uses the global setTimeout and setInterval, but can be configured to use custom implementations.
TimeoutManager methods available
TimeoutManager provides the following methods: timeoutManager.setTimeoutProvider, timeoutManager.setTimeout, timeoutManager.clearTimeout, timeoutManager.setInterval, and timeoutManager.clearInterval.
setTimeoutProvider usage and timing
setTimeoutProvider is used to set a custom implementation of setTimeout, clearTimeout, setInterval, and clearInterval functions, called a TimeoutProvider. 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.
setTimeoutProvider use case for performance
A custom TimeoutProvider may be useful if event loop performance issues occur with thousands of queries. It could also support timer delays longer than the global setTimeout maximum delay value of about 24 days.
TimeoutProvider type definition
TimeoutProvider is defined as: type ManagedTimerId = number | { [Symbol.toPrimitive]: () => number }; type TimeoutProvider<TTimerId extends ManagedTimerId = ManagedTimerId> = { readonly setTimeout: (callback: TimeoutCallback, delay: number) => TTimerId; readonly clearTimeout: (timeoutId: TTimerId | undefined) => void; readonly setInterval: (callback: TimeoutCallback, delay: number) => TTimerId; readonly clearInterval: (intervalId: TTimerId | undefined) => void; }. TimeoutProvider implementations must handle timer ID objects that can be converted to number via Symbol.toPrimitive because runtimes like NodeJS return objects from their global setTimeout and setInterval functions.
TimeoutProvider timer coalescing performance consideration
Timers are performance sensitive. Short-term timers with delays less than 5 seconds tend to be latency sensitive, while long-term timers may benefit more from timer coalescing, which batches timers with similar deadlines together using data structures like a hierarchical time wheel.
setTimeoutProvider example
import { timeoutManager, QueryClient } from '@tanstack/react-query'
import { CustomTimeoutProvider } from './CustomTimeoutProvider'
timeoutManager.setTimeoutProvider(new CustomTimeoutProvider())
export const queryClient = new QueryClient()
setTimeout method signature and behavior
timeoutManager.setTimeout(callback, delayMs) schedules a callback to run after approximately delay milliseconds, like the global setTimeout function. The callback can be canceled with timeoutManager.clearTimeout. It returns a timer ID, which may be a number or an object that can be coerced to a number via Symbol.toPrimitive.
clearTimeout method signature and behavior
timeoutManager.clearTimeout(timerId) cancels a timeout callback scheduled with setTimeout, like the global clearTimeout function. It should be called with a timer ID returned by timeoutManager.setTimeout.
clearTimeout example
import { timeoutManager } from '@tanstack/react-query'
const timeoutId = timeoutManager.setTimeout(
() => console.log('ran at:', new Date()),
1000,
)
timeoutManager.clearTimeout(timeoutId)
setInterval method signature and behavior
timeoutManager.setInterval(callback, intervalMs) schedules a callback to be called approximately every intervalMs, like the global setInterval function. It returns a timer ID, which may be a number or an object that can be coerced to a number via Symbol.toPrimitive.
clearInterval method signature and behavior
timeoutManager.clearInterval(intervalId) cancels an interval, like the global clearInterval function. It should be called with an interval ID returned by timeoutManager.setInterval.
clearInterval example
import { timeoutManager } from '@tanstack/react-query'
const intervalId = timeoutManager.setInterval(
() => console.log('ran at:', new Date()),
1000,
)
timeoutManager.clearInterval(intervalId)