Throttling & Debouncing

Throttling & Debouncing

ยท

4 min read

Understanding the practical application of knowledge is the key to mastering it.

Throttling

You are a developer of an e-commerce website where you implemented the search bar which helps the customer to search for their required items. This feature incorporates API calls on every Input to display the suggestions. If a customer type "s" you need to make a GET request to an API endpoint and display the suggestions.

Now, the customer tries searching for "Samsung mobile" and therefore you will be making 13 API requests to display the suggestion box for that particular word. 13 API calls just for a suggestion display is very expensive. Hence, the best solution here can be to make API calls in a desired interval of time. To clarify, the first API call will be made when a user inputs "s" and then the next API call will not be made on the next input but after a desired amount of time which can be a delay of 300 milliseconds.

Hence This explains the Throttling effect: After typing "s" when 300ms will be passed user would be somewhere near "samsu" and in this state again an API call will be made to GET the suggestions based on "samsu" keyword.

In this approach instead of making 5 API calls for "samsu" keyword, we make 2 API calls and this won't affect the user experience because the time difference between typing "s" and "samsu" is not that huge when it comes to the user side but it is very expensive when it comes to the API calls.

Let us dig deep into the implementation of throttling:

Initially, we just get the input element and print the value in the console.

const inputText = document.getElementById("inputText");
inputText.addEventListener('input', (e) => {
  const thisTarget = event.target;
  console.log(thisTarget.value);
});

implementation of throttling demand delay of API calls(here we see it as console.log).

So, we follow the steps of creating a throttle function :

S1: create a function that takes functions as arguments and performs throttle.

S2: create a function that prints the value to the console.

/* take function as parameter = cb, and assign default value to delay */
function throttle(cb, delay = 800) {  
  let wait = false;

/* returns a function that execute cb at the first call and then wait remains 
true for 800ms hence cb is not executed for 800ms. */
  return (...args) => {
    if (wait) {
      return;
    }

    cb(...args);
    wait = true;
    setTimeout(() => {
      wait = false;
    }, delay);
  }
}

function handleKeyPress(value) {
  console.log(value);
}

S3: wrap printFunction in throttleCreatorfunction and call it inside the event listener.

const throtteldFunction = throttle(handleKeyPress);

const inputText = document.getElementById("inputText");
inputText.addEventListener('input', (e) => {
  const thisTarget = event.target;
  throtteldFunction(thisTarget.value);
});

Implementation on JsFiddle https://jsfiddle.net/whiletrueee/7txecLu6/28/

Debouncing

Now, when the customer hit the search button to load the page for given input again a GET request to an API endpoint is made to load the page data.

Assume a customer kept pressing the search button for n numbers of times continuously which will cause n numbers of GET requests to an API endpoint. Eventually, this is not good for websites as API calls are very expensive and the UI will flicker to display the loader and the loaded page if requests are made frequently. Therefore we implement a function in such a manner that if the user clicks a button for the first time it runs the underlying code but if the user kept on pressing it further within a short period the function must not execute. And this is what debouncing is all about.

Let us see the implementation.

Here(in debounceTwo), initially, the timer is undefined and the function will be called.

If the timer is not undefined that means it has an id returned from setTimeout and the timer will be undefined after the delay of 1000ms.

If the button is clicked before 1000ms has elapsed clearTimeout will reset the timer to 1000ms.

regarding debounceOne try understanding it on your own and experience the implementation here: https://jsfiddle.net/whiletrueee/z9b6xu58/46/

/* debounce method 1 */
function debounceOne(func, delay = 1000) {
  let timer;
  return (...args) => {
    clearTimeout(timer);
    timer = setTimeout(() => {
      func.apply(this, args);
    }, delay);
  };
}

/* debounce method 2 */
function debounceTwo(func, delay = 1000) {
  let timer;
  return (...args) => {
    if (!timer) {
      func(...args);
    }
    clearTimeout(timer);
    timer = setTimeout(() => {
      timer = undefined;
    }, delay);
  };
}
function handleClick() {
  console.log("clicked");
}
const debouncedClick1 = debounceOne(handleClick);
const debouncedClick2 = debounceTwo(handleClick);

document.getElementById("clickme1").addEventListener('click', debouncedClick1);

document.getElementById("clickme2").addEventListener('click', debouncedClick2);

I wish this blog would have helped you in learning the concept of debouncing and throttling. ๐Ÿ‘€See you in my next blog, till then take care and keep ๐Ÿง‘โ€๐Ÿ’ป developing.

ย