DEV Community

HidetoshiYanagisawa
HidetoshiYanagisawa

Posted on

Boost Your JavaScript Performance with the Debounce Technique!

Hello readers! Today, we'll dive deep into the JavaScript debounce technique. By leveraging this method, you can efficiently control high-frequency event triggers, enhancing the performance of your web pages.

Table of Contents

  1. What is debounce?
  2. Implementing debounce
  3. Practical Examples
  4. Benefits and Considerations of debounce
  5. Conclusion

1. What is debounce?

Debounce is a technique to control the processing of high-frequency events. It ensures that a function is executed only if a certain interval has passed without another event trigger. This suppresses unnecessary function executions, preventing potential performance issues.


2. Implementing debounce

Here's a simple JavaScript implementation of the debounce function:

function debounce(func, wait) {
    let timeout;
    return function(...args) {
        const context = this;
        clearTimeout(timeout);
        timeout = setTimeout(() => {
            func.apply(context, args);
        }, wait);
    };
}
Enter fullscreen mode Exit fullscreen mode

This function takes the actual function (func) to be executed and a waiting time (wait) as arguments.


3. Practical Examples

Let's look at some practical uses of the debounce function we've just created.

Controlling Window Resize Events

const debouncedFunction = debounce(() => {
    console.log('Debounced!');
}, 300);

window.addEventListener('resize', debouncedFunction);
Enter fullscreen mode Exit fullscreen mode

In this example, even if the window resize event is triggered, the console.log('Debounced!'); will only execute 300 milliseconds after the last resize event.

Controlling API Requests on Input

const inputElement = document.querySelector('#search-input');

inputElement.addEventListener('keyup', debounce((event) => {
    fetchApi(event.target.value);
}, 500));
Enter fullscreen mode Exit fullscreen mode

Here, instead of making an API request every time a user types into a search form, the request is only made 500 milliseconds after the last key input, given that no new key inputs occur within that interval.


4. Benefits and Considerations of debounce

Benefits

  • Performance Boost: By controlling high-frequency event processing, you can reduce unnecessary operations.
  • Enhanced User Experience: Maintain a smooth user interaction while only executing essential processes.

Considerations

  • Proper handling of context is crucial inside the debounce function to use this correctly.
  • Setting the right wait time is key to balancing user experience and performance.

5. Conclusion

The debounce technique is a powerful tool for effectively controlling high-frequency event processing in JavaScript. Implementing this can significantly improve web page performance and user experience. Use it wisely, and you'll surely see its benefits.


I hope you found this article insightful. If you did, please don't forget to give it a thumbs up or leave a comment! Happy coding!

Top comments (7)

Collapse
 
noblica profile image
Dušan Perković

Hey nice article! But instead of using apply and switching function contexts, maybe you could've just returned an arrow function. So the code in 2. could be something like:

function debounce(func, wait) {
    let timeout;
    return (...args) => {
        clearTimeout(timeout);
        timeout = setTimeout(() => {
            func(args);
        }, wait);
    };
}
Enter fullscreen mode Exit fullscreen mode

Context switching can be tricky, and isn't seen that often in the wild anymore, so it might confuse some younger devs.

Otherwise, debouncing can be really useful, especially if you're implementing some kind of searchbox that should respond to every keystroke.

Collapse
 
j4k0xb profile image
j4k0xb • Edited

Then it's not possible anymore to call the debounced function with a custom this later (which is needed in some cases)
Keeping the normal function and apply just makes it more flexible with no real downsides...

Collapse
 
noblica profile image
Dušan Perković

Yeah, but it's not needed in this case, so why have it?
In which cases do you think this is needed, specifically?

Thread Thread
 
j4k0xb profile image
j4k0xb • Edited

as long as it doesnt abstract too much, general purpose is better than limiting the functionality to a specific use-case (the 2-3 examples from this post)

classes/functions from third party libraries that rely on this...

Foo.prototype.bar = debounce(Foo.prototype.bar, 100);
Enter fullscreen mode Exit fullscreen mode

vue options api:

export default defineComponent({
  data: { a: 1 },
  methods: {
    onKeyUp: debounce(function() {
      console.log(this.a);
    }, 500)
  }
})
Enter fullscreen mode Exit fullscreen mode
Thread Thread
 
noblica profile image
Dušan Perković

I agree, if you're dealing with something like this, you should use it.

But in general - I don't think it's a good idea, especially if you are starting a new project, or working in even a semi-modern stack.
If you don't need it (and if you're working on a more modern stack, there's a big chance you're using the composition API, and definitely not assigning functions to prototypes), you shouldn't use it. Less code is always better.

Collapse
 
martinpersson profile image
Martin Persson

When working with React there is a neet customHook you could use.

import { useEffect, useState } from "react"

function useDebounce<T>(value: T, delay?: number): T {
  const [debouncedValue, setDebouncedValue] = useState(value)

  useEffect(() => {
    const timer = setTimeout(() => setDebouncedValue(value), delay || 500)

    return () => {
      clearTimeout(timer)
    }
  }, [value, delay])

  return debouncedValue
}

export default useDebounce
Enter fullscreen mode Exit fullscreen mode

This hook will delay the update of the value until after the specified delay (default 500ms) has passed since the last change. You can use it to prevent rapid firing of events like typing in a search field. Just import and use useDebounce with the value you want to debounce, and the hook will take care of the rest

Collapse
 
efpage profile image
Eckehard

Debounce is really helpful, but this applies to a short time range of about 100 ms. If your timeout is too long you get a risk of blocking your event completely, as it constantly gets retriggerd.

I would recommend to add a second timeout for the timeout, that defines a maximum wait time. So, you can supress fast events, but grant access for at least every second or so.