DEV3 Technologies home

DEV3 Developer Forum

How do I write a debounce function in JavaScript, and what is the difference from throttle?

JavaScript helpSolved0 views
dev3 ·

My search input fires an API call on every keystroke. I want to wait until the user stops typing. How do I implement debounce and when should I throttle instead?

#javascript#debounce#performance

0

1 reply

dev3 · Accepted answer

Debounce waits until calls stop for N ms, then runs once (good for search boxes, resize end, autosave). Throttle runs at most once per N ms while events keep coming (good for scroll and mousemove).

Debounce

function debounce(fn, wait = 300) {
  let timer;
  const debounced = (...args) => {
    clearTimeout(timer);
    timer = setTimeout(() => fn(...args), wait);
  };
  debounced.cancel = () => clearTimeout(timer);
  return debounced;
}

const onInput = debounce((e) => search(e.target.value), 300);
input.addEventListener('input', onInput);

Throttle

function throttle(fn, wait = 200) {
  let last = 0;
  return (...args) => {
    const now = Date.now();
    if (now - last >= wait) {
      last = now;
      fn(...args);
    }
  };
}
window.addEventListener('scroll', throttle(updateProgress, 100));

In React

Create the debounced function once, not on every render:

const debounced = useMemo(() => debounce(search, 300), []);
useEffect(() => () => debounced.cancel(), [debounced]);

Or debounce the value:

function useDebounced(value, ms = 300) {
  const [v, setV] = useState(value);
  useEffect(() => {
    const t = setTimeout(() => setV(value), ms);
    return () => clearTimeout(t);
  }, [value, ms]);
  return v;
}

Then fetch in an effect that depends on the debounced value.

Tips

  • Pair debounce with AbortController so out-of-order responses are discarded.
  • For scroll animation prefer requestAnimationFrame or CSS over throttle.
  • lodash.debounce supports leading/trailing options if you need immediate-first-call behaviour.

Pitfall: debounce returning a new function each render in React means the timer is never shared and nothing is actually debounced.

0

Your reply

Every post is reviewed by DEV3 before it appears. Usually reviewed within 24 hours.

Markdown supported. Use ``` for code blocks. Images are not allowed.