본문으로 건너뛰기

TimeoutManager

TimeoutManager는 TanStack Query에서 setTimeoutsetInterval 타이머를 처리합니다.

TanStack Query는 타이머를 사용해 쿼리 staleTimegcTime 같은 기능뿐만 아니라 재시도, 스로틀링, 디바운싱도 구현합니다.

기본적으로 TimeoutManager는 전역 setTimeoutsetInterval을 사용하지만, 대신 사용자 지정 구현을 사용하도록 구성할 수 있습니다.

사용 가능한 메서드는 다음과 같습니다:

timeoutManager.setTimeoutProvider

setTimeoutProvider를 사용하여 setTimeout, clearTimeout, setInterval, clearInterval 함수의 사용자 지정 구현인 TimeoutProvider를 설정할 수 있습니다.

수천 개의 쿼리로 인해 이벤트 루프 성능 문제가 발생하는 경우 유용할 수 있습니다. 사용자 지정 TimeoutProvider는 전역 setTimeout의 최대 지연 값인 약 24일보다 긴 타이머 지연도 지원할 수 있습니다.

애플리케이션의 모든 timer에 동일한 provider가 일관되게 사용되도록 QueryClient 또는 쿼리를 생성하기 전에 setTimeoutProvider를 호출하는 것이 중요합니다. 서로 다른 TimeoutProviders는 상대방의 timer를 취소할 수 없기 때문입니다.

import { timeoutManager, QueryClient } from '@tanstack/react-query'
import { CustomTimeoutProvider } from './CustomTimeoutProvider'

timeoutManager.setTimeoutProvider(new CustomTimeoutProvider())

export const queryClient = new QueryClient()

TimeoutProvider

타이머는 성능에 매우 민감합니다. 단기 타이머(예: 지연 시간이 5초 미만인 타이머)는 지연 시간에 민감한 경향이 있는 반면, 장기 타이머는 타이머 병합, 즉 마감 시간이 비슷한 타이머를 계층적 타임 휠 같은 데이터 구조를 사용해 함께 일괄 처리하는 방식에서 더 큰 이점을 얻을 수 있습니다.

NodeJS 같은 런타임은 전역 setTimeoutsetInterval 함수에서 객체를 반환하므로, TimeoutProvider 타입은 구현에서 Symbol.toPrimitive을 통해 number로 변환할 수 있는 타이머 ID 객체를 처리하도록 요구합니다. TimeoutProvider 구현은 내부적으로 타이머 ID를 숫자로 강제 변환하거나 { [Symbol.toPrimitive]: () => number }을 구현하는 자체 사용자 지정 객체 타입을 자유롭게 반환할 수 있습니다.

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
}

timeoutManager.setTimeout

setTimeout(callback, delayMs)은 전역 setTimeout 함수처럼 약 delay밀리초 후에 실행되도록 콜백을 예약합니다.콜백은 timeoutManager.clearTimeout으로 취소할 수 있습니다.

타이머 ID를 반환하며, 이는 숫자이거나 Symbol.toPrimitive을 통해 숫자로 강제 변환할 수 있는 객체일 수 있습니다.

import { timeoutManager } from '@tanstack/react-query'

const timeoutId = timeoutManager.setTimeout(
() => console.log('ran at:', new Date()),
1000,
)

const timeoutIdNumber: number = Number(timeoutId)

timeoutManager.clearTimeout

clearTimeout(timerId)은 전역 clearTimeout 함수처럼 setTimeout으로 예약된 타임아웃 콜백을 취소합니다. timeoutManager.setTimeout이 반환한 타이머 ID를 인수로 전달하여 호출해야 합니다.

import { timeoutManager } from '@tanstack/react-query'

const timeoutId = timeoutManager.setTimeout(
() => console.log('ran at:', new Date()),
1000,
)

timeoutManager.clearTimeout(timeoutId)

timeoutManager.setInterval

setInterval(callback, intervalMs)은 전역 setInterval 함수처럼 약 intervalMs마다 콜백이 호출되도록 예약합니다.

setTimeout과 마찬가지로 타이머 ID를 반환하며, 이는 숫자이거나 Symbol.toPrimitive를 통해 숫자로 강제 변환할 수 있는 객체일 수 있습니다.

import { timeoutManager } from '@tanstack/react-query'

const intervalId = timeoutManager.setInterval(
() => console.log('ran at:', new Date()),
1000,
)

timeoutManager.clearInterval

clearInterval(intervalId)은 전역 clearInterval 함수처럼 인터벌을 취소하는 데 사용할 수 있습니다. timeoutManager.setInterval이 반환한 인터벌 ID를 인자로 전달해 호출해야 합니다.

import { timeoutManager } from '@tanstack/react-query'

const intervalId = timeoutManager.setInterval(
() => console.log('ran at:', new Date()),
1000,
)

timeoutManager.clearInterval(intervalId)