JavaScript Debounce Function

A lightweight debounce implementation for rate-limiting function execution.

Implementation

/**
 * Creates a debounced function that delays invoking func until after wait
 * milliseconds have elapsed since the last time the debounced function was invoked.
 * @param {Function} func - The function to debounce
 * @param {number} wait - The number of milliseconds to delay
 * @param {boolean} immediate - If true, trigger on the leading edge instead of the trailing
 * @returns {Function} The debounced function
 */
function debounce(func, wait, immediate = false) {
  let timeout;

  return function executedFunction(...args) {
    const later = () => {
      timeout = null;
      if (!immediate) func.apply(this, args);
    };

    const callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);

    if (callNow) func.apply(this, args);
  };
}

Usage Examples

Search Input

const searchInput = document.getElementById('search');
const handleSearch = debounce((e) => {
  console.log('Searching for:', e.target.value);
  // Perform API call
}, 500);

searchInput.addEventListener('input', handleSearch);

Window Resize

const handleResize = debounce(() => {
  console.log('Window resized to:', window.innerWidth, window.innerHeight);
  // Recalculate layout
}, 300);

window.addEventListener('resize', handleResize);

React Hook Version

import { useCallback, useRef } from 'react';

function useDebounce(callback, delay) {
  const timeoutRef = useRef(null);

  const debouncedCallback = useCallback((...args) => {
    if (timeoutRef.current) {
      clearTimeout(timeoutRef.current);
    }

    timeoutRef.current = setTimeout(() => {
      callback(...args);
    }, delay);
  }, [callback, delay]);

  return debouncedCallback;
}

// Usage
function SearchComponent() {
  const handleSearch = useDebounce((value) => {
    console.log('Searching:', value);
  }, 500);

  return (
    <input
      onChange={(e) => handleSearch(e.target.value)}
      placeholder="Search..."
    />
  );
}

When to Use

  • User Input: Prevent API calls on every keystroke
  • Window Events: Limit expensive calculations during resize/scroll
  • Auto-save: Delay saving until user stops typing
  • Form Validation: Wait for user to finish input before validating

Performance Considerations

  • Choose appropriate delay values (typically 200-500ms for user input)
  • Consider using requestAnimationFrame for visual updates
  • For scroll events, consider throttling instead of debouncing