Logo

dev-resources.site

for different kinds of informations.

Debounce and Throttle

Published at
8/5/2020
Categories
javascript
debounce
functional
throttle
Author
nugetchar
Author
9 person written this
nugetchar
open
Debounce and Throttle

The problem

Recently, a student of mine was facing a performance challenge: he had a treatment to trigger when the user would resize the browser window.

What he first did was something like this:

function treatment() {
  if (window.innerWidth >= 1000) {
    // do some stuff
  }
}

window.onresize = treatment;

He then noticed the treatment function was being executed for every tiny resizing the user would make, causing slow performances. According to this, he wanted to find a better solution: he actually wanted to trigger the treatment only for a given screen size.

So, he put some if conditions.
It was a good step: the treatment would only be executed when the screen size would meet the condition.
But it was not enough: what if, there was a way to reduce drastically the number of executions, and still have the treatment done properly?

Debounce and Throttle

Debounce and Throttle are two operators you can find in some libraries. You can, also, implement them by yourself.
They anwser to a need for performance, by reducing the trigger count of a function.

Throttle allows you to execute a function only if a certain amount of time has passed since the last execution.
Let's say we have a throttled function:

function displayName(name) {
  console.log(`Name is ${name}`);
}

// We want the execution to be done at least 1s after the last execution
const throttled = throttle((name) => displayName(name), 1000);
throttled('Thomas'); // will execute displayName and display 'Thomas'
setTimeout(() => throttled('Bastien'), 1500); // will execute displayName and display 'Bastien'
throttled('Antoine'); // will not execute displayName

That might solve our problem... or not!
This will prevent intempestive executions: but while it does, it might also prevent crucial executions. If the user resize the window within the time interval, meet the condition and stop resizing before a new interval begins, the treatment will never be triggered.

We cannot risk it.

This is where debounce comes in handy.
Debounce will execute the function, only it will reset the interval everytime the event is dispatched and, once the user has finished to do whatever s.he wanted to do, the function will finally be executed.

This guarantee us the function will be executed soon or later. The downside, however, is you cannot expect graphic treatments to be executed properly with this operator, as there is literally a timeout before the treatment can be done.

Let's take the previous example and change throttle for debounce:

function displayName(name) {
  console.log(`Name is ${name}`);
}

// We want the execution to be done at least 1s after the last execution
const debounced = debounce((name) => displayName(name), 1000);

debounced('Thomas'); // (1) SHOULD execute displayName and display 'Thomas' AFTER 1s
setTimeout(() => debounced('Bastien'), 1500); // (2) will trigger after 1.5s, execute displayName and display 'Bastien'
debounced('Antoine'); // (3) will cancel (1) and set a new timeout.

As we can see, debounce allows the displayName function to be properly executed.
And so, in our case, we might want something like that:

function treatment() {
  if (window.innerWidth >= 1000) {
    // do some stuff
  }
}

window.onresize = debounce(() => treatment(), 100);

Operators implementation

I found the implementation in the excellent book Discover Functional JavaScript by Cristian Salcescu.

Throttle

function throttle(fn, interval) {
  let lastTime;
  return (...args) => {
    if(!lastTime || ((Date.now() - lastTime) >= interval)) {
      fn(...args);
      lastTime = Date.now();
    }
  }
}

Debounce

function debounce(fn, wait) {
  let timer;
  return (...args) => {
    clearTimeout(timer);
    timer = setTimeout(() => fn(...args), wait);
  }
}
debounce Article's
30 articles in total
Favicon
If you think debounce or onblur is not working in React, you can check it.
Favicon
Enhance Your React Native App with Debouncing for API Optimization
Favicon
Dboun
Favicon
React: Debouncing input with useEffect
Favicon
Debounce Method for Searching
Favicon
Optimizing React Performance with useDebounce.
Favicon
Understanding JavaScript Debounce and Throttling
Favicon
Debounce function with a return value using promises
Favicon
Introducing dwayne/elm-debouncer: Debounce or throttle your actions in Elm
Favicon
Debouncing De-coded
Favicon
Some Problems I Face When Building React Single Page Application And How I Solve Them
Favicon
Debounce Input in React
Favicon
Como aplicar debounce em input de busca sem lodash
Favicon
Debouncing: how to use it
Favicon
Debounce in Next.js
Favicon
Optimized React Search Bar πŸ”―
Favicon
Learn Debounce and Throttle
Favicon
Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ Throttle ΠΈ Debounce Π² React
Favicon
Debouncing in Javascript using a custom function or Lodash library.
Favicon
Debounce Function in Javascript πŸš€
Favicon
Debouncing TypeScript
Favicon
How to use Lodash debounce method?
Favicon
Debounce in JavaScript
Favicon
What is Debouncing? Search Suggestions - A Javascript Implementation
Favicon
Throttle and Debounce in React
Favicon
Debounce and Throttle
Favicon
useDebounce hook in React, Improve performance of your React app with Debouncing
Favicon
Debouncing (lodash) with React
Favicon
Use lodash.debounce inside a function component in React
Favicon
How to Debounce UIButton Taps

Featured ones: