bhavya_w
bhavya_w

Reputation: 10107

Difference between throttling and debouncing a function

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

To me, both seem to do the same the thing. I have checked these two blogs to find out, but I'm still having trouble understanding.

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

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

Upvotes: 572

Views: 255139

Answers (28)

Géry Ogam
Géry Ogam

Reputation: 8087

@SibevinWang’s answer provides detailed descriptions of debouncing and throttling for leading-edge, trailing-edge, and leading-edge and trailing-edge variants.

@amitdigga’s answer provides common use cases: trailing-edge debouncing of search requests triggered by key presses in a search bar and leading-edge throttling of gunshots triggered by mouse clicks in a shooting game.

Here we provide simple implementations of the debounce and throttle functions inspired by Lodash. Unlike Lodash, our versions return a promise, allowing the caller to access the result returned or any exceptions thrown by the callback at the trailing edge.

Debounce

function debounce(
  callback,
  delay,
  { leading = false, trailing = true, maxDelay } = {},
) {
  let prevTimerId;
  let prevReject;
  let leadingTime;
  return function debounced(...args) {
    const now = Date.now();
    if (prevTimerId === undefined) {
      leadingTime = now;
    } else {
      clearTimeout(prevTimerId);
      prevReject(new Error('aborted'));
    }
    return new Promise((resolve, reject) => {
      prevReject = reject;
      const call = () => {
        try {
          resolve(callback.apply(this, args));
        } catch (exception) {
          reject(exception);
        }
      };
      const isLeading = leading && prevTimerId === undefined;
      if (isLeading) {
        call();
      }
      prevTimerId = setTimeout(
        () => {
          prevTimerId = undefined;
          if (trailing && !isLeading) {
            call();
          }
        },
        maxDelay === undefined
          ? delay
          : Math.min(delay, leadingTime + maxDelay - now),
      );
    });
  };
}

Usage examples of trailing-edge debouncing with callback functions of any kind (returning or throwing, synchronous or asynchronous):

const debounced1 = debounce(x => x, 5000);
debounced1('foo').then(console.log, console.error);
debounced1('bar').then(console.log, console.error);
debounced1('baz').then(console.log, console.error);

const debounced2 = debounce(x => { throw x }, 5000);
debounced2(new Error('foo')).catch(console.error);
debounced2(new Error('bar')).catch(console.error);
debounced2(new Error('baz')).catch(console.error);

const debounced3 = debounce(x => Promise.resolve(x), 5000);
debounced3('foo').then(console.log, console.error);
debounced3('bar').then(console.log, console.error);
debounced3('baz').then(console.log, console.error);

const debounced4 = debounce(x => Promise.reject(x), 5000);
debounced4(new Error('foo')).catch(console.error);
debounced4(new Error('bar')).catch(console.error);
debounced4(new Error('baz')).catch(console.error);

Throttle

function throttle(callback, delay, { leading = true, trailing = false } = {}) {
  return debounce(callback, delay, { leading, trailing, maxDelay: delay });
}

Usage examples of leading-edge throttling with callback functions of any kind (returning or throwing, synchronous or asynchronous):

const throttled1 = throttle(x => x, 5000);
throttled1('foo').then(console.log, console.error);
throttled1('bar').then(console.log, console.error);
throttled1('baz').then(console.log, console.error);

const throttled2 = throttle(x => { throw x }, 5000);
throttled2(new Error('foo')).catch(console.error);
throttled2(new Error('bar')).catch(console.error);
throttled2(new Error('baz')).catch(console.error);

const throttled3 = throttle(x => Promise.resolve(x), 5000);
throttled3('foo').then(console.log, console.error);
throttled3('bar').then(console.log, console.error);
throttled3('baz').then(console.log, console.error);

const throttled4 = throttle(x => Promise.reject(x), 5000);
throttled4(new Error('foo')).catch(console.error);
throttled4(new Error('bar')).catch(console.error);
throttled4(new Error('baz')).catch(console.error);

Upvotes: 0

Sibevin Wang
Sibevin Wang

Reputation: 4558

Debouncing and throttling are techniques used to reduce the frequency of actions triggered in response to events. Both techniques accept a delay in milliseconds not to trigger actions more than once per delay, along with leading and trailing boolean options to trigger events at the start (leading edge) and the end (trailing edge) of the delay, respectively.

Debouncing

For each event:

  • set the timer;
  • if leading is true, trigger an action at the leading edge if the timer was not already running;
  • if trailing is true, trigger an action at the trailing edge if no other event occurs and the action was not already triggered at the leading edge.

Leading-edge debouncing:

--1-------2-3-------4-5-6-------> events
  |====|  |====|    |====|
  |       | |====|  | |====|
  |       |         |   |====|
--1-------2---------4-----------> actions

Trailing-edge debouncing:

--1-------2-3-------4-5-6-------> events
  |====|  |====|    |====|
            |====|    |====|
                        |====|
-------1---------3-----------6--> actions

Leading-edge and trailing-edge debouncing:

--1-------2-3-------4-5-6-------> events
  |====|  |====|    |====|
  |       | |====|  | |====|
  |       |         |   |====|
--1-------2------3--4--------6--> actions

Throttling

For each event:

  • set the timer if the timer was not already running;
  • if leading is true, trigger an action at the leading edge if the timer was not already running;
  • if trailing is true, trigger an action at the trailing edge if no other event occurs and the action was not already triggered at the leading edge.

Leading-edge throttling:

--1-------2-3-----4-5-6---> events
  |====|  |====|  |====|
--1-------2-------4-------> actions

Trailing-edge throttling:

--1-------2-3-----4-5-6---> events
  |====|  |====|  |====|
-------1-------3-------6--> actions

Leading-edge and trailing-edge throttling:

--1-------2-3-----4-5-6---> events
  |====|  |====|  |====|
--1-------2----3--4----6--> actions

So the key difference between debouncing and throttling is that debouncing sets the timer for all events, which ensures actions are triggered only after a delay without events. In contrast, throttling sets the timer only for events for which the timer was not already running, which ensures actions are triggered only after a delay, regardless of event occurrence.

Upvotes: 7

jesusverma
jesusverma

Reputation: 1745

Debouncing invokes a callback after a delay has elapsed since the last call to the debounced function.

function debounce(callback, delay) {
  let timeoutId;
  return function() {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => callback.apply(this, arguments), delay);
  };
}

function sayHello() {
  console.log('Hello!');
}

const sayHelloDebounced = debounce(sayHello, 3000);
sayHelloDebounced();

Throttle invokes a callback on the first call to the throttled function and ignores subsequent calls until a delay has elapsed.

function throttle(callback, delay) {
  let callEnabled = true;
  return function() {
    if (callEnabled) {
      callback.apply(this, arguments);
      callEnabled = false;
      setTimeout(() => callEnabled = true, delay);
    }
  };
}

function sayHello() {
  console.log('Hello!');
}

const sayHelloThrottled = throttle(sayHello, 3000);
sayHelloThrottled();

Upvotes: 4

amitdigga
amitdigga

Reputation: 7178

Differences

Debounce 1 second Throttle 1 second
Outputs if… 1 second has elapsed since the last input 1 second has elapsed since the last output
Delay between… input and output output and output

Explanation by use case

  • Search bar: Don't want to search for a term every time the user presses a key? Want instead to search after the user stopped typing for 1 second? Use debounce 1 second on key press.
  • Shooting game: Don't want to fire a pistol every time the user clicks the mouse? Want instead to fire at most every 1 second? Use throttle 1 second on mouse click.

Reversing their roles

  • Throttling the search for 1 second: If a user types "abcde", with each subsequent character getting typed every 0.6 seconds, then throttle will trigger a search at the "a" press. It will then ignore every press for the next 1 second, so "b" at 0.6 second will be ignored. Then it will again trigger a search at the "c" press at 1.2 seconds will again trigger a search, which resets the time. "d" at 1.8 seconds will be ignored. Finally it will again trigger a search at the "e" press at 2.4 seconds.
  • Debouncing the pistol for 1 second: When a user sees an enemy, he clicks the mouse, but debounce will not fire the pistol. He will click again several times in that second but it will still be ignored. Only after ceasing his clicks for a full second will the pistol finally fire, one single shot.

A "real life" comparison

There are some guards outside a bar. Guards allow a person who says "I want to go in" inside the bar. This is a normal scenario. Anyone saying "I want to go in" is allowed to go inside the bar.

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

There is another guard, the Debounce Guard (debounce 5 seconds). He likes people who bring mental rest to him for 5 seconds. So if any person says "I will go", the guard waits for 5 seconds. If no other person disturbs him in those 5 seconds, he allows the first person inside. But, if some other person interrupts and says "I will go" in those 5 seconds, he will reject the first one, and again start the 5 seconds of waiting, this time for the second person. If 5 seconds pass without interruption now, that second person will be let in, but not the first.

Upvotes: 253

Anshul
Anshul

Reputation: 9480

  • 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."

Source

Upvotes: 64

Donal
Donal

Reputation: 32763

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 in this demo, which shows when a debounced vs throttled event would fire based on mouse movement.

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.

Upvotes: 711

Ryan Taylor
Ryan Taylor

Reputation: 13465

It's simpler than the demos.

When throttle is being called it fires your function periodically (eg. every 20ms) – and once at the end.

Debounce only fires at the end (eg. 20ms after the last event).

So, as long as events continue to fire rapidly (eg. in intervals of less than 20ms), debounce will remain silent, while throttle will fire once every 20ms. Both will fire at the end, the difference is only throttle will also fire in-between at set intervals.

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 (possibly only once).


I like to think of throttle as "including debounce", they both make a final call after the events are done, but due to implementation details, the two don't always make this final call at the exact same time, making demos confusing.

Upvotes: 40

windmaomao
windmaomao

Reputation: 7680

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.

Updated 1-20-23

Throttle might not need setInterval, here's a new version I wrote recently which takes care of this as well.

function throttle(fn, delay) {
  let canFire = true
  let queue = []

  function pop() {
    if (queue.length < 1) return 

    const [that, args] = queue.pop()
    fn.apply(that, args)
    canFire = false
    setTimeout(() => {
      canFire = true
      pop()
    }, delay)
  }
  
  function push() {
    queue.push([this, arguments])
    if (canFire) pop()
  } 

  push.cancel = () => {
    queue = []
  }

  return push
}

Updated 11-09-23

I start to believe throttle is an add-on on top of debounce. Read this https://windmaomao.medium.com/throttle-is-a-debounce-add-on-80d4a6027ad4.

function throttle(fn, delay) {
  let h
  let queue = []

  function pop() {
    if (queue.length < 1) return 

    if (!h) {
      const [that, args] = queue.pop()
      fn.apply(that, args) 
      
      h = setTimeout(() => {
        h = null
        pop()
      }, delay)      
    }      
  }
  
  return function push() {
    queue.push([this, arguments])
    pop()
  } 
}

Upvotes: 11

Arham Chowdhry
Arham Chowdhry

Reputation: 762

enter image description here

Debouncing and Throttling in Javascript

Both functions help to postpone or limit the rate at which some functions are executed. This in turn helps in optimising our web apps.

What is a Throttling?

  • Throttling is the way in which we trigger the function within the given amount of time.
  • The first request is allowed to pass.
  • The original function is executed only once per specified time

Example: The below image depicts the click events which are fired at an interval/delay of 40ms, The events e2,e3, and e4 occurred within 40ms and hence did not get executed.

enter image description here

Code for throttling,

const trottle = function (fn, d) {
  let flag = true;        // to pass the first event

  return function () {
    if (flag) {
      fn();              // execute the decorative function
      flag = false;      // block the next fired events
      setTimeout(() => {
        flag = true;     // unblock the next fired events after a specified delay
      }, d);
    }
  };
};

A throttling function is commonly used in resizing or scrolling events.

What is debouncing?

  • Debouncing is a way in which we stop the function from being called if it was called recently.
  • Only the last request is allowed to pass.
  • The original function is executed only if the caller stops calling the decorated function for the specified amount of time.

Example: The below image depicts the click events which are fired only after a delay(100ms) is completed,

enter image description here

Events e1,e2,e3 and e4 were fired by the user but were not successfully executed because the consecutive event occurred within 100ms. (delay between e1 and e2 < 100ms or e2 and e3 < 100ms… etc) Event e4 successfully calls the decorated function because there is a delay of 100ms after it is fired by the user. Code for debouncing:

const debounce = function (fn, d) {
  let timer;

  return function () {
    clearTimeout(timer);           // clears/reset the timer if the event is triggered withing the delay
    timer = setTimeout(() => {     // execute the function
      fn();
    }, d);
  };
};

A debouncing function is commonly used to limit typing(input fields) or clicking events.

Debouncing and Throttling in Action:

enter image description here

Denouncing vs throttling You can visually see the difference here

Supporting documents:

https://www.geeksforgeeks.org/javascript-throttling/ https://www.geeksforgeeks.org/debouncing-in-javascript/

Difference Between throttling and debouncing a function

https://www.youtube.com/watch?v=TBIEArmPywU

Upvotes: 4

Yaroslav Larin
Yaroslav Larin

Reputation: 335

What really matters here, in most simple terms: if you have some action, that is continuously repeated for some period (such as mouse movement, or page resize events), and you need to run some function in response, but you don't want to react to every action (cause it may detriment the performance), you have 2 options:

  • debounce - you skip all incoming actions, except the last one (the 'last one' is defined by the 'wait' time period you set for debounce function, for example, 2s - it will consider that actions flood stopped, if no actions were taken for 2s, and then it will react. This strategy is reasonable if you don't care about regular updates, you just need to react at least once.
  • throttle - if you want to react 'on schedule', to make regular updates even if actions flood is endless, you make your function run at regular intervals (no more often, then the specified time interval), for example 2s throttling will mean that your response will be executed an once if action is taken, but no less then 2s after that. So with continuous actions flood your response will be run on 0s, 2s, 4s, 6s, 8s...

Upvotes: 0

Uthman
Uthman

Reputation: 9837

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

Upvotes: 118

ocodo
ocodo

Reputation: 30319

How debouncing works in hardware.

Debouncing is the process of removing noise from a digital signal. When a button is pressed, the signal bouncing around can cause the button to be registered as being pressed multiple times. Debouncing removes this noise so that the button is only registered as being pressed once. Picture a ruler being bounced on the edge of a desk, and imagine metal contacts inside a switch bouncing like this.

Better still, look at this diagram, showing the switch noise caused by bouncing.

We use resistors and capacitors of properly calculated ratings to smooth out the signal for n ms.

Explain how signal throttling works in hardware.

Signal throttling is the process of limiting the number of times a signal can be registered. This is often used to prevent a button from being registered as being pressed multiple times in a short period of time.

I prefer the term gating, but that's because I'm into electronic music production.

We open the gate at the end of each throttle period, and allow the signal to pass, and then close the gate again, for the next throttle period.

Explain how debouncing works in software.

Debouncing in software is often accomplished by using a timer. When the button is pressed, the timer is started. If the button is pressed again before the timer expires, the timer is reset. This ensures that the button can only be registered as being pressed once per debounce period.

In many implementations of debounce, we create a debounced version of the function which is embedded in a closure containing a timer (or gate). When the timer delay expires we set it it null again. The actual function only runs when the timer is null. Usually, this means when we first call the debounced function, it'll run once, then subsequent calls to it will be effectively cancelled until the delay time has elapsed.

In some implementations of debounce, while a stream of calls are fired and the timer hasn't expired, the timer will be restarted. Only calling the function after the bouncing has stopped. This is usually called a trailing debounce.

Explain how throttling works in software.

Throttling in software is often accomplished by using a counter. When the button is pressed, the counter is incremented. If the button is pressed again before the counter reaches a certain threshold, the counter is reset. This limits the number of times the button can be registered as being pressed in a given period of time. It's good to visualise this as a pulse or beat, which opens and closes a gate while calls are being sent to the throttle.

Rate limiting is another way to think of a throttle.

Why is this such a common cause of confusion?

In many many use cases a debounce or throttle will get you the results you want, especially if the software implementation you're using allows you to chain, trail, or lead your throttle / debounce.

Still, I hope all the answers here and this one have helped you understand more clearly.

They're very similar.

Upvotes: 3

The major difference between debouncing and throttling is that debounce calls a function when a user hasn't carried out an event in a specific amount of time, while throttle calls a function at intervals of a specified amount of time while the user is carrying out an event.

Upvotes: 1

Gil Epshtain
Gil Epshtain

Reputation: 9831

A picture is worth a thousand words

Throttle Throttle

Debounce Debounce

Notice the Debounce will not fire until the events flow stops. However, Throttle will fire an event each interval.

(Thanks to css-tricks)

Upvotes: 32

Dapeng Li
Dapeng Li

Reputation: 3632

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.

Upvotes: 250

Karthikeyan Ganesan
Karthikeyan Ganesan

Reputation: 2035

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

Upvotes: 0

Rajeev
Rajeev

Reputation: 11

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.

Upvotes: 1

ItshakF
ItshakF

Reputation: 19

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.

Upvotes: 2

CodeBiker
CodeBiker

Reputation: 3263

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.

Upvotes: 1

Johan Bergens
Johan Bergens

Reputation: 111

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.

Upvotes: 0

A dev
A dev

Reputation: 948

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.

Upvotes: 6

bajran
bajran

Reputation: 1503

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

Upvotes: 9

Guy
Guy

Reputation: 13336

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.

Upvotes: 29

Pranay Binju
Pranay Binju

Reputation: 621

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/

Upvotes: 1

Oleh Devua
Oleh Devua

Reputation: 384

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.

Upvotes: 5

neo
neo

Reputation: 350

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

Upvotes: 4

John Weisz
John Weisz

Reputation: 32012

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.

Upvotes: 34

GibboK
GibboK

Reputation: 73988

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.

Upvotes: 22

Related Questions