Angular 비동기 스로틀 가이드
비동기 스로틀은 스로틀 가이드에서 설명한 타이밍 동작을 유지하면서 Promise 결과, 재시도, 오류 콜백, 진행 중인 작업에 대한 제어 기능을 추가합니다.
스로틀된 작업이 필요한 값을 반환하거나 거부될 수 있을 때, 또는 재시도와 중단 지원이 필요할 때 사용합니다. 동기 스로틀 어댑터도 부수 효과로 비동기 함수를 호출할 수 있지만 결과 Promise를 관리하지는 않습니다.
API 선택하기
- Promise를 반환하는 핸들러에는
injectAsyncThrottledCallback을 사용합니다. - 수명 주기 메서드와 선택된 상태가 필요하면
injectAsyncThrottler를 사용합니다.
Angular 예시
import { injectAsyncThrottler } from '@tanstack/angular-pacer'
export class SaveComponent {
readonly saver = injectAsyncThrottler(
savePosition,
{ wait: 1000 },
(state) => ({
isExecuting: state.isExecuting,
isPending: state.isPending,
}),
)
}
이 가이드의 이후 핵심 코드 조각은 injectAsyncThrottler을 사용하며 Angular 주입 컨텍스트 안에서 실행된다고 가정합니다.
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 = injectAsyncThrottler(savePositionToServer, {
wait: 1000,
asyncRetryerOptions: {
maxAttempts: 3,
backoff: 'exponential',
baseWait: 500,
jitter: 0.2,
},
})
maxAttempts에는 첫 번째 시도가 포함됩니다. 스로틀은 논리적 실행을 제어하고 재시도는 각 실행 안의 시도를 제어합니다. 부수 효과가 있는 작업의 재시도를 활성화하기 전에 비동기 재시도 가이드를 참고합니다.
대기 작업 취소 및 활성 작업 중단하기
cancel()은 대기 중인 후행 실행을 지웁니다. 활성 작업을 중단하거나 현재 스로틀 간격을 재설정하지는 않습니다.abort()는 활성 실행을 중단합니다. 대기 중인 후행 작업은 지우지 않습니다.flush()는 대기 중인 후행 작업을 즉시 실행하고 그 결과를 반환합니다.
기반 API가 취소를 지원하면 스로틀러의 시그널을 전달합니다.
const saver = injectAsyncThrottler(
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()를 사용합니다.
Angular 수명 주기
어댑터는 소유자가 제거될 때 대기 작업을 취소하고 활성 작업을 중단합니다. onUnmount를 제공하면 이 기본 정리 동작을 대체하므로 사용자 정의 콜백에서 필요한 모든 수명 주기 작업을 수행해야 합니다. 사용자 정의 정리 과정에서 작업을 플러시하면 컴포넌트가 제거되는 동안 사용자 콜백이 실행될 수 있다는 점에 유의해야 합니다.
반응형 상태
어댑터는 셀렉터 인수가 반환한 상태만 구독합니다. 셀렉터가 없으면 어댑터 상태는 비어 있습니다. 일반적으로 컴포넌트나 서비스의 필드 초기화 구문과 같은 Angular 주입 컨텍스트에서 유틸리티를 생성하고 뷰에서 사용하는 필드만 선택합니다.
const throttler = injectAsyncThrottler(
savePositionToServer,
{ wait: 1000 },
(state) => ({
isPending: state.isPending,
isExecuting: state.isExecuting,
lastResult: state.lastResult,
}),
)
console.log(
throttler.state().isPending,
throttler.state().isExecuting,
throttler.state().lastResult,
)
옵션 함수와 수명 주기 콜백은 기반 공개 유틸리티 인스턴스를 받습니다. 위 예제처럼 해당 콜백 안에서 .store.state를 읽는 방식을 지원합니다. 렌더링 코드는 여기에 나온 선택된 어댑터 상태를 읽어야 합니다.
앱에서 유지한 선택 상태를 복원하려면 initialState로 부분 스냅샷을 전달합니다. 이 스냅샷은 기본값과 병합됩니다. 지속 가능한 필드만 복원합니다. 대기 중인 타이머와 활성 실행은 복원되지 않습니다.
isPending: 후행 실행이 예약되어 있는지 여부입니다.isExecuting: 래핑된 함수가 활성 상태인지 여부입니다.lastArgs: 후행 작업을 위해 보존한 가장 최근 인수입니다.lastResult: 가장 최근의 성공 결과입니다.lastExecutionTime,nextExecutionTime: 현재 타이밍 경계입니다.successCount,errorCount,settleCount: 실행 결과 횟수입니다.
어댑터 시그니처는 Angular API 레퍼런스를, 전체 옵션과 상태 타입은 공개 핵심 레퍼런스를 참고합니다.