debounce() and throttle()

How to make debounce and throttle function

debounce()

The Debounce technique allow to “group” multiple sequential calls in a single one.

Where to use

  • Optimize the code that triggers the same API request multiple times in a short time to only do it once at the end.
  • Debounce browser resize event so that the callback function is executed only after the resize is complete.
  • Show error message after finishing typing.

How to implement

js

function debounce(func, wait, immediate) {
  let timeout;
  return function (...args) {
        const context = this;
    const later = function () {
      timeout = null;
      if (!immediate) func.apply(context, args);
    };
    const callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callNow) func.apply(context, args);
  };
}

js

function handleResize() {
    console.log("resize done!", window.innerWidth;
}

window.addEventListener('resize', debounce(handleResize), 500));

throttle()

The throttle technique allows you to force a function to run only once every X milliseconds. throttle guarantees the execution of the function regularly, at least every X milliseconds.

Where to use

  • When you need to track the user's scroll to decide the dropdown position as above or below the input tag.

How to implement

js

function throttle(func, delay) {
  let timeoutId;
  let lastExecTime = 0;

  return function (...args) {
    const currentExecTime = new Date().getTime();
    const elapsedTime = currentExecTime - lastExecTime;

    const callNow = elapsedTime > delay;

    if (callNow) {
      lastExecTime = currentExecTime;
      func.apply(this, args);
    } else {
      clearTimeout(timeoutId);
      timeoutId = setTimeout(() => {
        lastExecTime = new Date().getTime();
        func.apply(this, args);
      }, delay - elapsedTime);
    }
  };
}

js

function handleScroll() {
    console.log("handle scroll", window.scrollY);
}

window.addEventListener('scroll', throttle(handleScroll, 100));