바닐라 비동기 스로틀 가이드
비동기 스로틀은 스로틀 가이드에서 설명한 타이밍 동작을 유지하면서 Promise 결과, 재시도, 오류 콜백, 진행 중인 작업 제어 기능을 추가합니다.
스로틀된 작업이 필요한 값을 반환하거나 거부될 수 있거나 재시도 및 중단 지원이 필요할 때 사용합니다. 동기 Throttler는 부수 효과로 비동기 함수를 호출할 수 있지만 그 결과로 생성되는 Promise는 관리하지 않습니다.
빠른 시작
호출 가능한 함수만 필요하다면 asyncThrottle을 사용합니다.
import { asyncThrottle } from '@tanstack/pacer'
const savePosition = asyncThrottle(
async (position: number) => {
const response = await fetch('/api/position', {
method: 'POST',
body: JSON.stringify({ position }),
})
if (!response.ok) throw new Error('Save failed')
return response.json()
},
{ wait: 1000 },
)
const result = await savePosition(42)
메서드, 상태 또는 콜백이 필요하다면 AsyncThrottler를 사용합니다.
import { AsyncThrottler } from '@tanstack/pacer'
const saver = new AsyncThrottler(savePositionToServer, {
wait: 1000,
onSuccess: (result, args) => {
console.log('Saved position:', args[0], result)
},
onError: (error, args) => {
console.error('Save failed:', args[0], error)
},
})
const result = await saver.maybeExecute(42)
기본 에지 동작은 leading: true 및 trailing: true입니다. 첫 호출은 즉시 실행됩니다. 간격 중의 호출은 한 번의 후행 실행을 위해 유지되는 인수를 업데이트합니다.
Promise 결과
maybeExecute()는 Promise를 반환합니다. 즉시 실행이나 후행 실행은 그 결과로 이행됩니다. 다른 호출이 대기 중인 후행 작업을 교체하면 이전의 대기 중인 Promise는 스로틀러의 현재 lastResult로 이행됩니다.
call A ─── execute A ─── result A
call B ───┐
├─ call C replaces B ─── execute C
Promise B ──────────────────┘ resolves with result A
Promise C ────────────────────────────────────────── resolves with result C
교체된 호출은 더 새로운 후행 실행을 기다리지 않습니다. 모든 호출에 자체 실행과 결과가 필요하다면 비동기 큐를 사용합니다.
비동기 스로틀러는 현재 실행이 여전히 활성 상태인 동안 다음 예약 실행을 시작하지 않습니다. wait 간격은 계속 스로틀 타이밍을 제어하지만 Promise 생명주기로 인해 이후 작업의 예약 시점이 늦어질 수 있습니다.
선행 및 후행 실행
에지 조합은 동기 스로틀과 동일합니다.
leading | trailing | 동작 |
|---|---|---|
true | true | 즉시 실행하고 한 번의 후행 실행을 위해 가장 최근 호출을 유지합니다. 기본값입니다. |
true | false | 즉시 실행하고 간격 중에 이루어진 호출은 버립니다. |
false | true | 첫 실행 전에 한 간격을 기다린 다음 각 간격에서 가장 최근 호출을 유지합니다. |
false | false | 함수를 실행하지 않고 호출을 기록합니다. |
디바운스와 달리 간격 중의 호출은 간격을 다시 시작하지 않습니다. 대기 중인 후행 인수만 교체합니다.
오류 및 콜백
비동기 스로틀러는 각 실제 실행 전후에 다음 콜백을 제공합니다.
onSuccess(result, args, throttler)는 성공 후 실행됩니다.onError(error, args, throttler)는 실행의 재시도가 실패한 후 실행됩니다.onSettled(args, throttler)는 어느 결과든 완료된 후 실행됩니다.
onError가 없으면 throwOnError의 기본값이 true이므로 실패 시 실행을 소유한 Promise가 거부됩니다. onError를 제공하면 이 기본값이 false로 바뀌고 Promise는 현재 lastResult로 이행됩니다. 기본 동작을 재정의하려면 throwOnError를 명시적으로 설정합니다.
콜백은 실행을 나타내며 maybeExecute()의 모든 호출을 나타내지는 않습니다. 교체되거나 버려진 호출은 실행 콜백을 발생시키지 않습니다.
실패한 실행 재시도
각 실행에 사용되는 재시도기를 asyncRetryerOptions로 설정합니다.
const saver = new AsyncThrottler(savePositionToServer, {
wait: 1000,
asyncRetryerOptions: {
maxAttempts: 3,
backoff: 'exponential',
baseWait: 500,
jitter: 0.2,
},
})
maxAttempts에는 첫 시도가 포함됩니다. 스로틀은 논리적 실행을 제어하고 재시도는 각 실행 안의 시도를 제어합니다. 부수 효과가 있는 작업에 재시도를 활성화하기 전에 비동기 재시도 가이드를 참고합니다.
대기 중인 작업 취소 및 활성 작업 중단
cancel()은 대기 중인 후행 실행을 제거합니다. 활성 작업을 중지하거나 현재 스로틀 간격을 재설정하지는 않습니다.abort()는 활성 실행을 중단합니다. 대기 중인 후행 작업은 제거하지 않습니다.flush()는 대기 중인 후행 작업을 즉시 실행하고 결과를 반환합니다.
기반 API가 취소를 지원한다면 스로틀러의 신호를 전달합니다.
const saver = new AsyncThrottler(
async (position: number) => {
return fetch('/api/position', {
method: 'POST',
body: JSON.stringify({ position }),
signal: saver.getAbortSignal() ?? undefined,
})
},
{ wait: 1000 },
)
saver.abort()
신호를 사용하지 않고 abort()를 호출하면 재시도 관리는 중지되지만 임의의 Promise를 강제로 중지할 수는 없습니다.
안전하게 재설정하기
reset()은 기본 상태를 복원하지만 예약된 시간 제한을 제거하지 않으며 활성 작업의 중지를 보장하지도 않습니다. 필요하다면 먼저 생명주기를 정리합니다.
saver.cancel()
saver.abort()
saver.reset()
설정
wait와 enabled에는 값 또는 스로틀러 인스턴스를 받는 함수를 지정할 수 있습니다. setOptions()는 새 옵션을 기존 설정에 병합합니다.
saver.setOptions({
enabled: (throttler) => throttler.store.state.errorCount < 3,
wait: (throttler) =>
throttler.store.state.successCount < 10 ? 500 : 1000,
})
변경된 wait 값은 기존 후행 작업의 일정을 다시 잡지 않습니다. 이후의 예약과 실행에 적용됩니다. setOptions()를 통해 스로틀러를 비활성화하면 대기 중인 후행 작업이 취소됩니다.
재사용할 수 있고 타입 검사를 거친 옵션 객체를 정의하려면 asyncThrottlerOptions()를 사용합니다.
상태
클래스는 throttler.store에 상태를 저장합니다.
애플리케이션이 유지한 일부 상태를 복원하려면 부분 스냅샷을 initialState로 전달합니다. 이 스냅샷은 기본값과 병합됩니다. 지속 가능한 필드만 복원합니다. 대기 중인 타이머와 활성 실행은 복원되지 않습니다.
일반적으로 유용한 속성은 다음과 같습니다.
isPending: 후행 실행이 예약되어 있는지 나타냅니다.isExecuting: 래핑된 함수가 활성 상태인지 나타냅니다.lastArgs: 후행 작업을 위해 유지한 가장 최근 인수입니다.lastResult: 가장 최근의 성공 결과입니다.lastExecutionTime과nextExecutionTime: 현재 타이밍 경계입니다.successCount,errorCount,settleCount: 실행 결과 횟수입니다.
전체 상태와 옵션 타입은 AsyncThrottler API 레퍼런스를 참고합니다.