Difference Between throttling and debouncing a function

Javascript

Javascript Problem Overview


Can anyone give me a in-simple-words explanation about the difference between throttling and debouncing a function for rate-limiting purposes.

To me both seems to do the same the thing. I have checked these two blogs to find out :

http://remysharp.com/2010/07/21/throttling-function-calls

http://benalman.com/projects/jquery-throttle-debounce-plugin/

Javascript Solutions


Solution 1 - Javascript

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 - Javascript

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 will be called at most once per specified period.
  • Debounce: the original function will 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 - Javascript

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.

Further explanation for input-output comparision with real life

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.

Solution 4 - Javascript

Throttle (1 sec): Hello, I am a robot. As long as you keep pinging me, I will keep talking to you, but after exactly 1 second each. If you ping me for a reply before a second is elapsed, I will still reply to you at exactly 1 second interval. In other words, I just love to reply at exact intervals.

Debounce (1 sec): Hi, I am that ^^ robot's cousin. As long as you keep pinging me, I am going to remain silent because I like to reply only after 1 second is passed since the last time you pinged me. I don't know, if it is because I have an attitude problem or because I just don't like to interrupt people. In other words, if you keeping asking me for replies before 1 second is elapsed since your last invocation, you will never get a reply. Yeah yeah...go ahead! call me rude.


Throttle (10 min): I am a logging machine. I send system logs to our backend server, after a regular interval of 10 minutes.

Debounce (10 sec): Hi, I am not cousin of that logging machine. (Not every debouncer is related to a throttler in this imaginary world). I work as a waiter in a nearby restaurant. I should let you know that as long as you keep adding stuff to your order, I will not go to the kitchen for execution of your order. Only when 10 seconds have elapsed after you last modified your order, I will assume that you are done with your order. Only then will I go and execute your order in the kitchen.


Cool Demos: https://css-tricks.com/debouncing-throttling-explained-examples/

Credits for the waiter analogy: https://codeburst.io/throttling-and-debouncing-in-javascript-b01cad5c8edf

Solution 5 - Javascript

Throttling enforces a maximum number of times a function can be called over time. As in "execute this function at most once every 100 milliseconds."

Debouncing enforces that a function not be called again until a certain amount of time has passed without it being called. As in "execute this function only if 100 milliseconds have passed without it being called."

ref

Solution 6 - Javascript

In layman's terms:

Debouncing will prevent a function from running while it is still being called frequently. A debounced function will only run after it has been determined that it is no longer being called, at which point it will run exactly once. Practical examples of debouncing:

  • Auto-saving or validating the contents of a text-field if the user "stopped typing": the operation will only be done once, AFTER it has been determined that the user is no longer typing (no longer pressing keys).

  • Logging where users rest their mouse: the user is no longer moving their mouse, so the (last) position can be logged.

Throttling will simply prevent a function from running if it has run recently, regardless of the call frequency. Practical examples of throttling:

  • Implementations of v-sync are based on throttling: the screen will only be drawn if 16ms elapsed since the last screen draw. No matter how many times the screen refresh functionality is called, it will only run at most once every 16ms.

Solution 7 - Javascript

Debouncing allows you to manage the frequency of calls that a function can receives. It combines multiple calls that happen on a given function so that repeated calls that occur before the expiration of a specific time duration are ignored. Basically debouncing ensures that exactly one signal is sent for an event that may be happening several times.

Throttling restricts the frequency of calls that a function receives to a fixed time interval. It is used to ensuring that the target function is not invoked more often than the specified delay. Throttling is the reduction in rate of a repeating event.

Solution 8 - Javascript

It's simple.

They do the exact same thing (rate limiting) except while throttle is being called it'll fire your wrapped function periodically, and debounce won't. Debounce just (tries to) call your function once at the very end.

Example: If you're scrolling, throttle will slowly call your function while you scroll (every X milliseconds). Debounce will wait until after you're done scrolling to call your function.

Solution 9 - Javascript

A real-life analogy that personally helps me remember:

  • debounce = a conversation. you wait for the other person to finish speaking before you reply.
  • throttle = a drum bit. you only play notes on a simple 4/4 drum bit.

Use cases for debounce:

  • Typing. You want to do something after the user stopped typing. So waiting 1sec after the last keystroke makes sense. Each keystroke restarts the wait.
  • Animation. You want to shrink back an element after the user stopped hovering over it. Not using debounce might cause an erratic animation as a result of the cursor unintentionally moving between the "hot" and "cold" zones.

Use cases for throttle:

  • Scrolling. You want to react to scrolling but limit the amount of calculations made, so doing something every 100ms is enough to prevent potential lag.
  • Mouse move. Same as scrolling but for mouse move.
  • API calls You want to fire an API call on certain UI events but want to limit the number of API calls you make not to overload your server.

Solution 10 - Javascript

Throttling > Throttling enforces a maximum number of times a function can be called > overtime. As in "execute this function at most once every 100 > milliseconds." Say under normal circumstances you would call this > function 1,000 times over 10 seconds. If you throttle it to only once > per 100 milliseconds, it would only execute that function at most 100 > times

(10s * 1,000) = 10,000ms
10,000ms / 100ms throttling = 100 maximum calls

Debouncing

> Debouncing enforces that a function not be called again until a > certain amount of time has passed without it being called. As in > "execute this function only if 100 milliseconds have passed without it > being called."

Perhaps a function is called 1,000 times in a quick burst, dispersed over 3 seconds, then stops being called. If you have debounced it at 100 milliseconds, the function will only fire once, at 3.1 seconds, once the burst is over. Each time the function is called during the burst it resets the debouncing timer

source:- throttle and debouncing

Solution 11 - Javascript

the lodash Library suggests the following article https://css-tricks.com/debouncing-throttling-explained-examples/ which detailed explain the difference between Debounce and Throttle and their origination

Solution 12 - Javascript

throtle is just a wrapper around debounce which makes debounce to call passed function in some period of time, if debounce delays a function call on period of time which is bigger then specified in throtle.

Solution 13 - Javascript

Suppose we have a callback function "cb" to be called on event "E". Let "E" getting triggered 1000 times in 1 second, hence there would be 1000 calls to "cb". That is 1 call/ms. To optimize we can either use:

  • Throttling: With throttling of (100ms), "cb" would be called on [100th ms, 200th ms, 300th ms, ... 1000th ms]. That is 1 call/100 ms. Here 1000 calls to "cb" optimized to 10 calls.
  • Debouncing: With debouncing of (100ms), "cb" would be called only once on [1100th sec]. That is 100ms after the last trigger of "E" which happend on [1000th ms]. Here 1000 calls to "cb" optimized to 1 call.

Solution 14 - Javascript

Debouncing makes it so a function can only be executed after a certain amount of time since it was last invoked

function debounce(func,wait){
  let timeout
  return(...arg) =>{
    clearTimeout(timeout);
    timeout= setTimeout(()=>func.apply(this,arg),wait)
  }
}


function SayHello(){
  console.log("Jesus is saying hello!!")
}


let x = debounce(SayHello,3000)
x()

The throttle pattern limits the maximum number of times a given event handler can be called over time. It lets the handler be called periodically, at specified intervals, ignoring every call that occurs before this wait period is over.

function throttle(callback, interval) {
  let enableCall = true;

  return (...args)=> {
    if (!enableCall) return;

    enableCall = false;
    callback.apply(this, args);
    setTimeout(() => enableCall = true, interval);
  }
}


function helloFromThrottle(){
  console.log("Jesus is saying hi!!!")
}

const foo = throttle(helloFromThrottle,5000)
foo()

Solution 15 - Javascript

Putting debounce and throttle together can be very confusing, because they both share a parameter called delay.

enter image description here

Debounce. The delay is to wait till there's no more invokes anymore, then to invoke it. Very much like to close an elevator door: the door has to wait till no one tries to get in before closing.

Throttle. The delay is to wait with a frequency, then invokes for the last one. Very much like to fire a pistol gun, the gun just can't be fired beyond certain rate.


Let's take a look at the implementation to see in details.

function debounce(fn, delay) {
  let handle = null
  
  return function () {
    if (handle) {
      handle = clearTimeout(handle)
    }
    
    handle = setTimeout(() => {
      fn(...arguments)
    }, delay)
  }
}

Debounce, keeps interrupting the timeout until no more interruptions, and then fires fn.

function throttle(fn, delay) {
  let handle = null
  let prevArgs = undefined
  
  return function() {
    prevArgs = arguments
    if (!handle) {
      fn(...prevArgs)
      prevArgs = null
      handle = setInterval(() => {
        if (!prevArgs) {
          handle = clearInterval(handle)
        } else {
          fn(...prevArgs)
          prevArgs = null
        }
      }, delay)
    }
  }
}

Throttle, stores the last call arguments, and sets up an interval to fire until no past fires any more.

Similarities. They both have a delay time, and there's no fire during the delay, especially when there's only one fire. Both do not aggregate past events, so the number of events can be different than the actual fires.

Difference. The delay can be extended in debounce case with repeated events. Whereas the delay in the throttle case is fixed. So in general you get more fires from the throttle than debounce.

Easy to remember. Debounce groups bundle calls into one. Throttle keeps bundle calls within certain frequency.

Solution 16 - Javascript

As far as I understand, in simple terms Throttling - similar to calling setInterval(callback) for certain number of times i.e calling same function for certain number of times over time on occurrence of event and.. Debouncing - similar to calling setTImeout(callbackForApi) or calling a function after certain time has passed on occurrence of event. This link can be helpful- https://css-tricks.com/the-difference-between-throttling-and-debouncing/

Solution 17 - Javascript

For examples of typical uses cases, I recommend @Guy's answer. But the best way for me to understand these two concepts was to make it about pizzas. 

Let's say you're an amazing pizza-maker, and so customers are in your shop constantly demanding more pizzas.

Throttling: You decide you will only put out one pizza at the end of every hour, as long you received at least one request for pizza during that hour.

You receive 100 requests for pizzas in one hour, so you provide a pizza at the end of that hour. Then, you get no requests for pizza the next hour, so you don't put out a pizza. Then you get 10 requests for pizzas the next hour, and so you put out a pizza at the end of that hour.

Debouncing: You are getting annoyed about your customers constantly demanding pizzas, and so you decide you will only give them a pizza after they have stopped asking you for a full minute.

They demand pizzas for 30 minutes straight, but then they stop asking for a minute after that. At that point, you will give them one pizza.

Then they demand pizzas for 5 minutes straight, and stop asking for a minute after that. At that point, you give them another pizza.

Solution 18 - Javascript

Debounce:

Executes the function after the interval if function isn't being called within that interval.

Throttle:

Executes the function n times at fixed interval.

Solution 19 - Javascript

This article explains it rather well and has graphics too.

https://css-tricks.com/debouncing-throttling-explained-examples/

From the article (and with some clarifications): > The main difference between this (throttle) and debouncing is that throttle guarantees the execution of the function regularly, at least every X milliseconds.

Normally debounce calls the function at the end of a specified time and throttle calls when the first call to the throttled function is made. Sometimes debounce can take extra config that changes this to do the call at the beginning instead. Some implemenations of debounce can actually do what throttle does (see Lodash source code) when called with specific configs.

Solution 20 - Javascript

it’s in fact the way of limiting an event. For example, if you are listening on an event onclick, if it’s regular it will listen to every click you made.

If you use Throttle, it will set an interval between the time you want to listen to event for example listen to one click every second.

Debounce is a more restrictive one, it will only fire itself at the beginning or the ending of an event. For example, you are scrolling and you use Debounce, it will trigger only when you start and you finish to scroll.

Solution 21 - Javascript

Simple concept for throttle is clicking the submit button frequently in a form, we need to use throttle. So the submit function is prevent from frequent clicks. It saves the same requests pass into the function.

And about debounce, write a simple code with input text tag for searching some data from the server. oninput, you use the debounce so it removes the previous requests and pass the last typed word to the server

const throttle = (callback, time = 0) => {
    let throttle_req, count = 0;
     return async function () {
         var context = this, args = arguments;  
         if(throttle_req) return;  
         throttle_req = true; 
         if(time > 0)
         {
             callback.apply(context, args); 
             setTimeout(() => {
              throttle_req = false; 
             }, time || 200) 
         }
         else
         {
           let response = await callback.apply(context, args); 
            throttle_req = false; 
           return response;
         } 
     }
  }
const debounce = (callback, time = 0) => {
    let debounce_req;
    return function () {
        var context = this, args = arguments;
        clearTimeout(debounce_req) 
        debounce_req = setTimeout(() => {
             debounce_req = null;
             callback.apply(context, args);
        }, time || 200) 
    }
}

How we call: Just wrap your function with throttle or debounce to check the difference

Throttle ex: same button click more than 1 time

var throttleFunct = throttle(function(num) {
  console.log(num, "hello throttle")
}, 2000);
throttleFunct(300) //it execute. because its the first call
throttleFunct(400) //it won't execute

throttle async without time

var getDataAsync =  throttle(function(id, name) {
    return new Promise((resolve) => {  
      setTimeout(() => {
            resolve({name: name, id: id})
      }, 2000)
     }) 
});
async function test() {
let response = await getDataAsync(120, 'Sherley').then(resp => resp)  
console.log(response, "respond") //it execute. because its the first call
response = await getDataAsync(120, 'James').then(resp => resp)  
console.log(response, "respond2")//it executes 2 after first request
response = await getDataAsync(120, 'Jonathan').then(resp => resp)  
console.log(response, "respond3")//it executes 3 after second request
    }
    test()


Debounce For ex: search box autocomplete

var debounceFunct = debounce(function(num) {
  console.log(num+1)
}, 2000);
debounceFunct(300) //it won't execute and it cancelled
debounceFunct(400) // it executes and it replaced with the previous call. because this is the latest event fire

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionbhavya_wView Question on Stackoverflow
Solution 1 - JavascriptDonalView Answer on Stackoverflow
Solution 2 - JavascriptDapeng LiView Answer on Stackoverflow
Solution 3 - Javascriptamit77309View Answer on Stackoverflow
Solution 4 - JavascriptUsmanView Answer on Stackoverflow
Solution 5 - JavascriptAnshulView Answer on Stackoverflow
Solution 6 - JavascriptJohn WeiszView Answer on Stackoverflow
Solution 7 - JavascriptGibboKView Answer on Stackoverflow
Solution 8 - JavascriptRyan TaylorView Answer on Stackoverflow
Solution 9 - JavascriptGuyView Answer on Stackoverflow
Solution 10 - JavascriptbajranView Answer on Stackoverflow
Solution 11 - JavascriptneoView Answer on Stackoverflow
Solution 12 - JavascriptOleh DevuaView Answer on Stackoverflow
Solution 13 - JavascriptA devView Answer on Stackoverflow
Solution 14 - JavascriptjesusvermaView Answer on Stackoverflow
Solution 15 - JavascriptwindmaomaoView Answer on Stackoverflow
Solution 16 - JavascriptPranay BinjuView Answer on Stackoverflow
Solution 17 - JavascriptCodeBikerView Answer on Stackoverflow
Solution 18 - JavascriptRajeevView Answer on Stackoverflow
Solution 19 - JavascriptJohan BergensView Answer on Stackoverflow
Solution 20 - JavascriptItshakFView Answer on Stackoverflow
Solution 21 - JavascriptKarthikeyan GanesanView Answer on Stackoverflow