createSingleRequest
단일 비동기 실행만 허용하는 함수 래퍼를 생성하는 팩토리 함수입니다.
반환된 함수로 래핑한 비동기 함수는 진행 중인 호출이 있을 때 중복 실행되지 않고, 완료 후에는 다시 호출할 수 있습니다.
debounce/throttle는 함수의 중복 호출을 방지하는 데 대부분의 경우에 효과적입니다.
하지만, debounce/throttle는 비동기 작업의 완료를 보장하지 않기 때문에 다음과 같은 한계가 있습니다:
debounce/throttle시간이 API 응답 시간보다 짧을 경우: 비동기 작업이 완료되지 않은 상태에서다시 호출될 수 있습니다.debounce/throttle시간이 API 응답 시간보다 길 경우: 비동기 작업이 완료되었지만버튼과 같은 요소가 여전히비활성화되어 있을 수 있습니다.즉각적인 반응을 원하는 경우:debounce/throttle는 호출을 지연시키기 때문에 사용자에게즉각적인 반응을 보여주기에 제한적입니다.debounce/throttle은시간을 기반으로 동작하기 때문에얼마나 자주 실행되는지가 중요하지중복 호출 여부를 파악하기 어렵습니다.
위와 같은 한계점을 대응하고자 한다면 createSingleRequest를 사용할 수 있습니다.
Code
Interface
typescript
function createSingleRequest(
key?: string
): <T, Args extends unknown[]>(
callback: (...args: Args) => Promise<T>
) => (...args: Args) => Promise<T | undefined>;
Usage
기본 사용법
typescript
import { createSingleRequest } from '@modern-kit/utils';
const singleRequest = createSingleRequest();
const wrappedFetch = singleRequest(fetchData);
wrappedFetch(); // 실행됨
wrappedFetch(); // 진행 중이므로 무시됨 (undefined 반환)
wrappedFetch(); // 진행 중이므로 무시됨 (undefined 반환)
// 첫 번째 호출이 완료된 뒤에는 다시 호출 가능
여러 비동기 함수가 하나의 잠금 공유
typescript
import { createSingleRequest } from '@modern-kit/utils';
const singleRequest = createSingleRequest();
const wrappedSubmit = singleRequest(submitForm);
const wrappedSync = singleRequest(syncData);
// wrappedSubmit이 진행 중이면 wrappedSync 호출도 블록됨 (같은 잠금 공유)
wrappedSubmit();
wrappedSync(); // undefined 반환, 실행되지 않음
인자 전달
typescript
import { createSingleRequest } from '@modern-kit/utils';
const singleRequest = createSingleRequest();
const wrappedFetch = singleRequest(async (id: number) => {
const res = await fetch(`/api/items/${id}`);
return res.json();
});
const data = await wrappedFetch(42); // 콜백에 42가 전달됩니다.