Skip to content

Instantly share code, notes, and snippets.

@drianoaz
Created June 23, 2023 14:20
Show Gist options
  • Save drianoaz/9c56cf85faac134b867ddb2c3b030d91 to your computer and use it in GitHub Desktop.
Save drianoaz/9c56cf85faac134b867ddb2c3b030d91 to your computer and use it in GitHub Desktop.
Simple debounce function using typescript
import { debounce } from './debounce';
describe('debounce', () => {
test('should debounce function calls', () => {
jest.useFakeTimers();
const mockFunction = jest.fn();
const delay = 500;
const debouncedFunction = debounce(mockFunction, delay);
// Call the debounced function multiple times within the delay period
debouncedFunction();
debouncedFunction();
debouncedFunction();
// After the delay period, the function should only be called once
expect(mockFunction).not.toHaveBeenCalled();
jest.advanceTimersByTime(delay);
expect(mockFunction).toHaveBeenCalledTimes(1);
jest.useRealTimers();
});
test('should pass arguments to the debounced function', () => {
jest.useFakeTimers();
const mockFunction = jest.fn();
const delay = 500;
const debouncedFunction = debounce(mockFunction, delay);
// Call the debounced function with arguments
const arg1 = 'Hello';
const arg2 = 'World';
debouncedFunction(arg1, arg2);
// After the delay period, the function should be called with the arguments
jest.advanceTimersByTime(delay);
expect(mockFunction).toHaveBeenCalledWith(arg1, arg2);
jest.useRealTimers();
});
test('should cancel and reset the debounce timer', () => {
jest.useFakeTimers();
const mockFunction = jest.fn();
const delay = 500;
const debouncedFunction = debounce(mockFunction, delay);
// Call the debounced function multiple times within the delay period
debouncedFunction();
debouncedFunction();
debouncedFunction();
// Cancel the debounce timer before it expires
jest.advanceTimersByTime(delay - 100);
debouncedFunction();
// After the delay period, the function should not be called
jest.advanceTimersByTime(100);
expect(mockFunction).not.toHaveBeenCalled();
jest.useRealTimers();
});
});
type DebouncedFunction<T extends unknown[]> = (...args: T) => void;
/**
* Creates a debounced function that delays the execution of the provided function `func`
* until a specified delay has passed without any further function calls. Only the last
* function call within the delay period will be executed.
*
* @template T - The type of the original function's arguments.
* @param {(...args: T) => void} func - The original function to be debounced.
* @param {number} delay - The delay in milliseconds.
* @returns {DebouncedFunction<T>} - The debounced function.
*
* @example
* // Example usage of debounce function
*
* function saveChanges() {
* console.log('Saving changes...');
* // Perform the actual save operation
* }
*
* const debouncedSaveChanges = debounce(saveChanges, 1000);
*
* // Simulating rapid calls to the debounced function
* debouncedSaveChanges(); // No immediate call
* debouncedSaveChanges(); // No immediate call
* debouncedSaveChanges(); // No immediate call
*
* // After 1000ms of inactivity, 'Saving changes...' will be logged and saveChanges will be invoked.
**/
export function debounce<T extends unknown[]>(
func: (...args: T) => void,
delay: number,
): DebouncedFunction<T> {
let timeoutId: ReturnType<typeof setTimeout> | undefined;
return function (...args: T) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
func(...args);
}, delay);
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment