DEV Community

Cover image for What is Debouncing? Search Suggestions - A Javascript Implementation
Bingo's Code
Bingo's Code

Posted on • Updated on

What is Debouncing? Search Suggestions - A Javascript Implementation

Introduction

Having spent a large portion of the last few months working on my Front End Development skills, I figured I could share my learnings about various concepts with other developers who are on the same journey. I'll start with a technique used to help improve the performance of web applications.

Debouncing is a technique used to limit the number of times a function executes. It is used when there are DOM events that fire execution of a function. For example, when there are API calls made because of a DOM event, it's wise to have some control over the frequency of calls made to reduce load on the backend and improve the experience on the front-end.

How it Works

Let's consider the way the auto-suggestion functionality of a search bar works, like what google and other search services in retail websites offer.

Google Search Auto-suggestion Example

To implement something like this we will need an event listener to be attached to the search input field and make a call to fetch suggestions every time a new character is typed in or removed. We can use the onkeyup event from the browser to detect the addition or removal of a character and trigger an API call to fetch the suggestions. Lets understand this through an example,

index.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Javascript Debouncing</title>
    </head>
    <body>
        <input type="text" onkeyup="getSuggestions()"/>
        <script src="index.js"></script>
    </body>
</html>

For the sake of understanding debouncing, let's not call an actual API, but instead just use a counter to check how many times the function/API would be called.

index.js

let counter = 0;
const getSuggestions = () => {
    //Calls API to get Data for each character
    console.log("Fetching Data...", counter++);
}

With the above code, if a user is searching for "Apple Laptops", she/he would enter 13 characters thus invoking the auto-suggest API 13 times. The output would be,

OUTPUT:

Fetching Data... 0
Fetching Data... 1
Fetching Data... 2
Fetching Data... 3
Fetching Data... 4
Fetching Data... 5
Fetching Data... 6
Fetching Data... 7
Fetching Data... 8
Fetching Data... 9
Fetching Data... 10
Fetching Data... 11
Fetching Data... 12

Think about this, just to search for apple laptops I make 13 different calls for suggestions? Is this necessary?

If I'm typing the word "Apple" quickly, I wouldn't want to see the suggestions for each keystroke like "A", "Ap", "App", "Appl", that's not great User Experience. I would ideally only want to see the suggestions for when I have finished typing "Apple" or whenever I pause while typing. Let's try to remedy our index.js to consider this.

Let's assume that an average user types at a pace that the time between consecutive keystrokes is roughly under 300ms. That would mean that if a user takes more than 300ms between two keystrokes, the user has paused. This time can be tweaked to be more realistic for what you think the average speed of typing an individual might have. Now when the user waits longer than 300ms, an API call can be made with the search term. We can translate this into code by making use of the setTimeout method.

index.js

let counter = 0;
const getSuggestions = () => {
    //Calls API to get Data
    console.log("Fetching Data...", counter++);
}

const debounce = function (fn, d) {
    let timer;
    return function () {
    let context = this, args = arguments;
    clearTimeout(timer);
    timer = setTimeout(() => {
            fn.apply(context, args);
        }, d)
    }
}

const debounceForData = debounce(getSuggestions, 300);

Also, do not forget to call the debounceForData method in the index.html.

<input type="text" onkeyup="debounceForData()"/>

In the index.js, you can see that the debounce method calls the getSuggestions method using the setTimeout method. This code will now clear the timer every time there is a new keystroke. Only if the timer is not cleared before it completes, the getSuggestions function will be executed.

Conclusion

So you can see that debouncing is a way of grouping together a series of closely spaced events into one to help limit the number of times a function is executed.

You can see how this works with the search field in the Amazon website. In the first gif you can see that I deliberately typed the characters slowly and you can see a suggestion API call being made with each change in the input field. (adding and deleting characters, and I think even with a focus event)

Call for each character

In the second one you can see that I typed much faster and the number of suggestion API calls made is lesser than the number of characters typed. Debouncing Magic!

Debouncing in Action

There is another technique that can be used to achieved this, Throttling. It works a little differently but helps with performance as well. We can explore that in another post.

Feel free to leave any feedback, suggestions and comments.

Latest comments (3)

Collapse
 
kosich profile image
Kostia Palchyk

Hey, Sabareesh! Nice article!

Hope this helps with your next posts: dev.to has a way to format your code even better! Three backticks + language + your code + closing three backticks, e.g. :

'''js
…your code…
'''

(just backtick instead of ')

And you get nice:

debounce(x => {
  console.log('hello world!');
}, 100)
Enter fullscreen mode Exit fullscreen mode

See dev.to help for more.

Keep on writing 👍

Collapse
 
sbrshkappa profile image
Bingo's Code

Thank you Kostia. That's a useful tip, I've made that change to the code snippets on this post.

Collapse
 
leigh864 profile image
leigh864

Nice example, so that clearTimeout is really important, I understand now. Thanks
Looking forward to throttle explanation