Let's (De)bounce with JavaScript

Let's (De)bounce with JavaScript

Think of the APIs!

ยท

4 min read

Introduction

Let's suppose you are building a search component in your project. In this component, the user can search any terms and your goal is to provide the user with search suggestions.

The easiest solution would be to send a request to your API or backend every time the user types a character right? Well.. yes and no.

Yes, it is very simple to implement it in your code, and you'd be done for the day But bombarding your API with requests for each character would turn out to be pretty inefficient, not to mention expensive too!

So what is the solution, I hear you ask? Allow the user to type anything but ensure that network calls are kept to a minimum, thus saving you a performance headache and not emptying your wallet.

And for that, we turn to debouncing.

image.png

What is debouncing?

If we look at the actual definition of debouncing, it stems from the field of electronics, where an emitter might send multiple signals to a receiver even though the event was fired once. This condition is called bouncing.

image.png

Thus to resolve this, we just react to the initial event or request that is received and ignore any other subsequent events until a certain threshold is passed.

The quick and simple method

Let's return to the example we discussed in the Introduction. Firstly let's see how a regular search component would work.

Inside our HTML file, we will create a simple input element which will act as our search component.

<input type="text" id="searchfield" placeholder="Search anything..." />

And inside our JavaScript file, we will write logic that will act as our poor man's API call. Using an eventListener, it will run a callback function based on the type of event invoked (in our case it is input).

const search = document.getElementById("searchfield")

const executeSearch = (query) => {
  console.log(query.length > 0 ? `You searched ${query}` : "Search empty")
}

search.addEventListener("input", (e) => executeSearch(e.target.value))

Refer to the CodePen below for the same (type your search query and check the output on your browser's Console).

You can note that on each character entered, our poor man's API is being fired. And if we're to scale that for larger projects (think Amazon or Netflix), having so many calls would be expensive right?

Now let's see how debouncing helps overcome this.

Now let's spice it up with Debouncing

Let's go back to our JavaScript file, now instead of the current callback implementation, we will instead call a separate function handleDebounce() inside which we will pass a callback function executeSearch() and a delay (in ms)


const handleDebounce = debounce(query => executeSearch(query), 1000)

search.addEventListener("input", (e) => handleDebounce(e.target.value));

Now inside our debounce method,

const debounce = (callbackfn, delay) => {
    let timeoutId;
    return (query) => {
        clearTimeout(timeoutId);
        timeoutId = setTimeout(() => {
            callbackfn(query)
        }, delay);
    };
};

Check out how our search component works after implementing debouncing (type your search query and check the output on your browser's Console).

All that exists is not magic

Let's now explore what happens in the code snippet above.

When a user initially types inside the input component, the debounce() method is initially run, and clearTimeout() executed. Next the setTimeout() is executed with our executeSearch() method after a specific delay.

Now things get interesting as the user keeps typing, the event listener gets executed on each character input, and so does debounce(). Thus on each instance of keypress, our previous instance of setTimeout gets cleared with clearTimeout and a new setTimeout is invoked with the delay specified. This cycle repeats until the user stops typing for the duration of the delay and executeSearch() can finally be executed.

image.png

Wrapping up!

We learned what is debouncing, what benefits it provides and how to implement it in our code.

While implementing debouncing might not make sense in small projects, as the lines of code increase or you work with a production codebase, you will understand what impact it has on user experience and the overall performance of your code.

  • Want to continue this discussion? Let's converse on Twitter
  • Curious about what I'm up to besides writing blogs? Check out my Github

Till next time, take care and cheers! ๐Ÿฅ‚

ย