Skip to content

Instantly share code, notes, and snippets.

@codebycarlos
Created February 20, 2024 09:56
Show Gist options
  • Save codebycarlos/5364d21bdcbd116f489da422bb97d99b to your computer and use it in GitHub Desktop.
Save codebycarlos/5364d21bdcbd116f489da422bb97d99b to your computer and use it in GitHub Desktop.
debounce
/**
* Creates a debounced function that delays invoking `func` only for subsequent
* calls within the `debounceDelayMs` period after the first call.
*
* - `func`: Function to debounce. Can be asynchronous.
* - `debounceDelayMs`: Milliseconds to delay subsequent calls.
* - Returns: A function returning a promise with `func`'s result.
*
* The first call to the debounced function is executed immediately, while
* subsequent calls within the `debounceDelayMs` period are debounced.
*
* @example
* const fetchUserData =
* debounce(() => fetch('/api/user').then(res => res.json()), 300);
*
* button.addEventListener('click', () => {
* fetchUserData().then(data => console.log(data));
* });
*/
export const debounce = <F extends (...args: any[]) => any>(
func: F,
debounceDelayMs: number
): ((...args: Parameters<F>) => Promise<ReturnType<F>>) => {
let timeout: ReturnType<typeof setTimeout> | undefined;
let isFirstCall = true;
return (...args: Parameters<F>): Promise<ReturnType<F>> =>
new Promise((resolve) => {
if (isFirstCall) {
isFirstCall = false;
resolve(func(...args));
} else {
if (timeout !== undefined) {
clearTimeout(timeout);
}
timeout = setTimeout(() => resolve(func(...args)), debounceDelayMs);
}
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment