debounce
debounce는 빠른 update 요청을 모아 wait window 뒤에 적용합니다. text input, resize 기반 값, 즉시 알릴 필요가 없는 high-frequency update에 유용합니다.
Signature
debounce(wait?: number): PipeAnyMiddlewarewait의 단위는 밀리초이며 기본값은 300입니다. 전달했다면 유한한 0 이상의 숫자여야 하며 0도 유효합니다. 잘못된 wait 값은 middleware 또는 timer를 설정하기 전에 RangeError를 던집니다.
예제
import { debounce } from '@ilokesto/state/middleware';
import { pipe } from '@ilokesto/state/utils';
const store = pipe
.use(debounce(250))
.create({ query: '' });
store.setState({ query: 'i' });
store.setState({ query: 'il' });
store.setState({ query: 'ilo' });persist와 함께 사용하기
debounce는 persist보다 먼저 선언하세요. 영속화는 최초 업데이트 요청이 아닌 실제 지연된 commit을 관찰합니다.
import { debounce, jsonStorage, persist } from '@ilokesto/state/middleware';
import { pipe } from '@ilokesto/state/utils';
type SearchState = { readonly query: string };
const decodeSearch = (value: unknown): SearchState | null => {
if (typeof value !== 'object' || value === null || !('query' in value)) return null;
return typeof value.query === 'string' ? { query: value.query } : null;
};
const store = pipe
.use(debounce(250))
.use(persist({ key: 'search', storage: jsonStorage(() => window.localStorage), decode: decodeSearch }))
.create<SearchState>({ query: '' });
await store.persist.rehydrate();반대 선언 순서는 계속 MIDDLEWARE_ORDER로 거부됩니다. 복원은 debounce를 기다리지 않고 즉시 commit합니다. flush()는 commit된 저장 대상을 기다리며 대기 중인 debounce 타이머를 강제로 실행하지 않습니다. history()와 debounce() 또는 throttle()의 조합 제한은 유지됩니다.
Function update
function update는 순서를 유지한 채 저장되고, timer가 실행될 때 누적된 current state를 기준으로 replay됩니다. 그래서 debounce window 안에서도 updater function끼리 조합됩니다.
Timing 주의점
timer가 실행되기 전까지 getState()는 이전에 commit된 state를 반환합니다. 모든 중간 write가 즉시 관찰되어야 하는 state에는 debounce를 쓰지 마세요. history()는 동기 commit이 필요하므로 이 pipe chain에 함께 쓸 수 없습니다.
Cleanup
debounce는 대기 중인 timer를 소유합니다. Store가 더 이상 필요 없으면 @ilokesto/state/middleware의 dispose(store)를 호출해 취소하세요. Disposal은 해당 store에만 적용되며 반복 호출해도 안전합니다. Cleanup 하나가 실패해도 등록된 모든 cleanup을 시도하며, 하나라도 실패하면 각 원래 thrown value가 담긴 AggregateError를 throw합니다.