Debouncing is a technique that delays running a function until a certain amount of time has passed without it being called again — it’s the standard fix for expensive operations triggered by rapid-fire events, like firing a search API request on every keystroke in a search box. Instead of running once per keystroke, a debounced handler waits until the user pauses typing before running.

JavaScript Program to Debounce a Function

function debounce(fn, delay) {
  let timerId;

  return function (...args) {
    clearTimeout(timerId);
    timerId = setTimeout(() => fn.apply(this, args), delay);
  };
}

// Example: a search handler that should only run once typing pauses
function searchApi(query) {
  console.log("Searching for:", query);
}

const debouncedSearch = debounce(searchApi, 300);

// Simulating rapid typing — only the LAST call within 300ms actually runs
debouncedSearch("j");
debouncedSearch("ja");
debouncedSearch("jav");
debouncedSearch("java");
debouncedSearch("javascript");

Output:

Searching for: javascript

Each call to debouncedSearch cancels the previous pending timer with clearTimeout() and starts a new one, so only the final call — "javascript" — actually survives long enough to fire, 300ms after the last keystroke. The earlier four calls never reach searchApi at all, which is exactly the point: debouncing collapses a burst of calls into one. This same pattern is used for window-resize handlers, autosave, and form-validation-as-you-type.