함수: useAsyncBatcher()
function useAsyncBatcher<TValue, TSelected>(
fn,
options,
selector): PreactAsyncBatcher<TValue, TSelected>;
정의 위치: preact-pacer/src/async-batcher/useAsyncBatcher.ts:235
항목의 비동기 배치를 관리하는 AsyncBatcher 인스턴스를 생성하는 Preact 훅입니다.
useBatcher 훅의 비동기 버전입니다. 동기 버전과 달리 이 비동기 배처는 다음을 지원합니다.
- 프로미스를 처리하고 배치 실행 결과를 반환합니다.
- 구성 가능한 오류 동작으로 오류를 처리합니다.
- 성공, 오류 및 완료 횟수를 별도로 추적합니다.
- 배치 실행 여부를 상태로 추적합니다.
- 배치 함수 실행 결과를 반환합니다.
기능:
- 구성 가능한 배치 크기 및 대기 시간
- getShouldExecute를 통한 사용자 지정 배치 처리 로직
- 배치 작업 모니터링을 위한 이벤트 콜백
- 실패한 배치 작업의 오류 처리
- 자동 또는 수동 배치 처리
배처는 다음 조건에 따라 항목을 모아 배치로 처리합니다.
- 최대 배치 크기(배치당 항목 수)
- 시간 기반 배칭(X밀리초 후 처리)
- getShouldExecute를 통한 사용자 지정 배치 처리 로직
오류 처리:
onError핸들러를 제공하면 오류 및 배처 인스턴스와 함께 호출됩니다.throwOnError가 true이면(onError 핸들러가 없을 때의 기본값) 오류가 발생합니다.throwOnError가 false이면(onError 핸들러가 있을 때의 기본값) 오류가 처리된 것으로 간주됩니다.- onError와 throwOnError를 함께 사용할 수 있으며, 오류가 발생하기 전에 핸들러가 호출됩니다.
- 내부 AsyncBatcher 인스턴스를 사용해 오류 상태를 확인할 수 있습니다.
상태 관리와 셀렉터
훅은 반응형 상태 관리에 TanStack Store를 사용합니다. 다음 두 가지 방식으로 상태 변경을 구독할 수 있습니다.
1. batcher.Subscribe HOC 사용(컴포넌트 트리 구독에 권장)
Subscribe HOC를 사용하면 컴포넌트 트리 깊은 곳의 상태 변경을 구독할 때
훅에 셀렉터를 전달할 필요가 없습니다. 자식 컴포넌트에서 상태를
구독하려는 경우에 적합합니다.
2. selector 매개변수 사용(훅 수준 구독)
selector 매개변수를 사용하면 어떤 상태 변경이 재렌더링을 트리거할지 지정할 수 있으며
관련 없는 상태가 변경될 때 불필요한 재렌더링을 방지하여 훅 수준의 성능을 최적화합니다.
기본적으로 반응형 상태 구독은 없습니다. 상태 추적을 명시적으로 활성화하려면
셀렉터 함수를 제공하거나 Subscribe HOC를 사용해야 합니다. 이렇게 하면 불필요한
재렌더링을 방지하고 컴포넌트가 업데이트되는 시점을 완전히 제어할 수 있습니다.
사용 가능한 상태 속성:
errorCount: 오류가 발생한 배치 실행 횟수failedItems: 배치 처리 중 실패한 항목 배열isEmpty: 배처에 처리할 항목이 없는지 여부isExecuting: 배치가 현재 비동기로 처리 중인지 여부isPending: 배처가 배치 처리를 트리거할 타임아웃을 기다리는지 여부isRunning: 배처가 활성 상태이며 항목을 자동으로 처리할지 여부items: 현재 배치 처리 대기 중인 항목 배열lastResult: 가장 최근 배치 실행 결과settleCount: 성공 또는 오류로 완료된 배치 실행 횟수size: 현재 배치 큐에 있는 항목 수status: 현재 처리 상태('idle' | 'pending' | 'executing' | 'populated')successCount: 성공적으로 완료된 배치 실행 횟수totalItemsProcessed: 모든 배치에서 처리된 전체 항목 수totalItemsFailed: 처리에 실패한 전체 항목 수
언마운트 동작
기본적으로 컴포넌트가 언마운트되면 훅은 대기 중인 배치를 취소하고 진행 중인 실행을 중단합니다.
getAbortSignal()의 중단 신호를 내부 작업(예: fetch)에 전달한 경우에만 Abort가 해당 작업을 취소합니다.
이를 사용자 지정하려면 onUnmount 옵션을 사용합니다. 예를 들어 대기 중인 작업을 대신 플러시하려면 다음과 같이 합니다.
const batcher = useAsyncBatcher(fn, {
maxSize: 10,
wait: 2000,
onUnmount: (b) => b.flush()
});
참고: 비동기 유틸리티에서 flush()는 Promise를 반환하며 정리 과정에서는 실행 후 결과를 기다리지 않습니다.
배치 함수가 Preact 상태를 업데이트하면 해당 업데이트가 컴포넌트가
언마운트된 뒤 실행될 수 있으며, 이 경우 "setState on unmounted component" 경고가 발생할 수 있습니다. 콜백을
onUnmount에서 flush와 함께 사용할 때 적절히 보호해야 합니다.
타입 매개변수
TValue
TValue
TSelected
TSelected = {
}
매개변수
fn
(items) => Promise<any>
options
PreactAsyncBatcherOptions<TValue, TSelected> = {}
selector
(state) => TSelected
반환값
PreactAsyncBatcher<TValue, TSelected>
예시
// Basic async batcher for API requests - no reactive state subscriptions
const asyncBatcher = useAsyncBatcher(
async (items) => {
const results = await Promise.all(items.map(item => processItem(item)));
return results;
},
{ maxSize: 10, wait: 2000 }
);
// Subscribe to state changes deep in component tree using Subscribe HOC
<asyncBatcher.Subscribe selector={(state) => ({ size: state.size })}>
{({ size }) => (
<div>Batch Size: {size}</div>
)}
</asyncBatcher.Subscribe>
// Opt-in to re-render when execution state changes at hook level (optimized for loading indicators)
const asyncBatcher = useAsyncBatcher(
async (items) => {
const results = await Promise.all(items.map(item => processItem(item)));
return results;
},
{ maxSize: 10, wait: 2000 },
(state) => ({
isExecuting: state.isExecuting,
isPending: state.isPending,
status: state.status
})
);
// Opt-in to re-render when results are available (optimized for data display)
const asyncBatcher = useAsyncBatcher(
async (items) => {
const results = await Promise.all(items.map(item => processItem(item)));
return results;
},
{ maxSize: 10, wait: 2000 },
(state) => ({
lastResult: state.lastResult,
successCount: state.successCount,
totalItemsProcessed: state.totalItemsProcessed
})
);
// Opt-in to re-render when error state changes (optimized for error handling)
const asyncBatcher = useAsyncBatcher(
async (items) => {
const results = await Promise.all(items.map(item => processItem(item)));
return results;
},
{
maxSize: 10,
wait: 2000,
onError: (error) => console.error('Batch processing failed:', error)
},
(state) => ({
errorCount: state.errorCount,
failedItems: state.failedItems,
totalItemsFailed: state.totalItemsFailed
})
);
// Complete example with all callbacks
const asyncBatcher = useAsyncBatcher(
async (items) => {
const results = await Promise.all(items.map(item => processItem(item)));
return results;
},
{
maxSize: 10,
wait: 2000,
onSuccess: (result) => {
console.log('Batch processed successfully:', result);
},
onError: (error) => {
console.error('Batch processing failed:', error);
}
}
);
// Add items to batch
asyncBatcher.addItem(newItem);
// Manually execute batch
const result = await asyncBatcher.execute();
// Access the selected state (will be empty object {} unless selector provided)
const { isExecuting, lastResult, size } = asyncBatcher.state;