Difference Between throttling and debouncing a function

Solution 1:

To put it in simple terms:

  • Throttling will delay executing a function. It will reduce the notifications of an event that fires multiple times.
  • Debouncing will bunch a series of sequential calls to a function into a single call to that function. It ensures that one notification is made for an event that fires multiple times.

You can visually see the difference here

If you have a function that gets called a lot - for example when a resize or mouse move event occurs, it can be called a lot of times. If you don't want this behaviour, you can Throttle it so that the function is called at regular intervals. Debouncing will mean it is called at the end (or start) of a bunch of events.

Solution 2:

Personally I found debounce harder to comprehend than throttle.

As both functions help you postpone and reduce the rate of some execution. Assuming you are calling decorated functions returned by throttle/debounce repeatedly...

  • Throttle: the original function be called at most once per specified period.
  • Debounce: the original function be called after the caller stops calling the decorated function after a specified period.

I found the last part of debounce crucial to understand the goal it's trying to achieve. I also found an old version of the implementation of _.debounce helps the understanding (courtesy of https://davidwalsh.name/function-debounce).

// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
_.debounce = function(func, wait, immediate) {
  var timeout;
  return function() {
    var context = this, args = arguments;
    var later = function() {
        timeout = null;
        if (!immediate) func.apply(context, args);
    };
    var callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callNow) func.apply(context, args);
  };
};

A far-fetched metaphor, but maybe could also help.

You have a friend named Chatty who likes to talk with you via IM. Assuming when she talks she sends a new message every 5 seconds, while your IM application icon is bouncing up and down, you can take the...

  • Naive approach: check every message as long as it arrives. When your app icon bounces, check. It's not the most effective way, but you are always up-to-date.
  • Throttle approach: you check once every 5 minutes (when there are new ones). When new message arrives, if you have checked anytime in the last 5 minutes, ignore it. You save your time with this approach, while still in the loop.
  • Debounce approach: you know Chatty, she breaks down a whole story into pieces, sends them in one message after another. You wait until Chatty finishes the whole story: if she stops sending messages for 5 minutes, you would assume she has finished, now you check all.

Solution 3:

Differences

+--------------+-------------------+-------------------+
|              |  Throttle 1 sec   |  Debounce 1 sec   |
+--------------+-------------------+-------------------+
| Delay        | no delay          | 1 sec delay       |
|              |                   |                   |
| Emits new if | last was emitted  | there is no input |
|              | before 1 sec      |  in last 1 sec    |
+--------------+-------------------+-------------------+

Explanation by use case:

  • Search bar- Don't want to search every time user presses key? Want to search when user stopped typing for 1 sec. Use debounce 1 sec on key press.

  • Shooting game- Pistol take 1 sec time between each shot but user click mouse multiple times. Use throttle on mouse click.

Reversing their roles:

  • Throttling 1 sec on search bar- If users types abcdefghij with every character in 0.6 sec. Then throttle will trigger at first a press. It will will ignore every press for next 1 sec i.e. bat .6 sec will be ignored. Then c at 1.2 sec will again trigger, which resets the time again. So d will be ignored and e will get triggered.

  • Debouncing pistol for 1 sec- When user sees an enemy, he clicks mouse, but it will not shoot. He will click again several times in that sec but it will not shoot. He will see if it still has bullets, at that time (1 sec after last click) pistol will fire automatically.

(Edited in 2021)

Explanation for real life scenario: (sorry if it make sense)

There are some guards outside a bar. Guard allows person who say "I will go" to let inside the bar. That is a normal scenario. Anyone saying "I will go" is allowed to go inside the bar.

Now there is a Throttle Guard (throttle 5 sec). He likes people who responds first. Anyone who says "I will go" first, he allows that person. Then he rejects every person for 5 sec. After that, again anyone saying it first will be allowed and others will be rejected for 5 sec.

There is another Debounce Guard (debounce 5 sec). He likes people who brings mental rest to him for 5 seconds. So if any person says "I will go", the guard wait for 5 seconds. If no other person disturbs him for 5 seconds, he allow the first person. If some other person says "I will go" in those 5 sec, he reject the first one. He again starts the 5 sec waiting for the second person to see if the second one can bring him the mental rest.