Page 1 of 1

Simple Debouncing Rate Topic: -----

#1 andrewsw  Icon User is online

  • lashings of ginger beer
  • member icon

Reputation: 6336
  • View blog
  • Posts: 25,545
  • Joined: 12-December 12

Posted 15 May 2016 - 05:27 AM

Debouncing "limits the rate at which a function can fire". When someone is resizing the window the resize event will fire many times. If we respond to each event with some detailed code then it could cause misbehaviour or sluggishness (or, at worst, a crash). Similarly, if the user repeatedly clicks a button, or leans on the keyboard, we want to limit our response to these events.

Debouncing Javascript Methods
Javascript Debounce Function



Throttling is similar. As discussed in the first article it is "the reduction in rate of a repeating event". For example, if a button is clicked 10 times quickly in succession we may only want to respond to 3 of these events. With debouncing, if a button is clicked rapidly within a certain time frame, we only want to respond to the last of these events. That is, "grouping multiple events in one".

Debounce and Throttle: a visual explanation



My simple example isn't original, it is this answer at stackoverflow, but I've created a vanilla Javascript version and added some code so that we can see what is happening. Read the entire topic for other more detailed versions and examples.

Here it is:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Debouncing</title>
</head>
<body>
<h1>Just Bouncing Around</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat.</p>

<script>
window.addEventListener('resize', function fn() {
    fn.x = fn.x || 0;
    console.log(++(fn.x));

    clearTimeout(window.resizeFinished);
    window.resizeFinished = setTimeout(function () {
        console.log('Resize finished.');
        var par = document.getElementById('thisone');
        if (!par.style.color || par.style.color == 'green') {
            par.style.color = 'red';
        } else {
            par.style.color = 'green';
        }
    }, 250);
}, false);
</script>
</body>
</html>


Basically, we are listening for the window's resize event. Each time it fires we clear the existing timeout and reset it for another 250ms. As long as the user is resizing the window quickly enough (within a 250ms interval) nothing will happen. Only when the user stops resizing (or slows down enough) will the last set timeout still be queued - will still exist - and its code will be executed 250ms later.

I've given the (formerly) anonymous function a name 'fn' so that we can effectively attach a static variable to it:
    fn.x = fn.x || 0;
    console.log(++(fn.x));

Make sure the console is visible in your browser then, as you resize the window, this number will display as 1,2,3, etc.. Only when you pause resizing will you see the text "Resize finished". (Of course, this is where you would put your detailed code.)

Here is the jQuery version which is almost identical:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Debouncing</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
</head>
<body>
<h1>Just Bouncing Around</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat.</p>
<script>
$(window).resize(function fn() {
    fn.x = fn.x || 0;
    console.log(++(fn.x));

    clearTimeout(window.resizeFinished);
    window.resizeFinished = setTimeout(function () {
        console.log('Resize finished.');
        var par = $('#thisone')[0]; // DOM object
        if (!par.style.color || par.style.color == 'green') {
            par.style.color = 'red';
        } else {
            par.style.color = 'green';
        }
    }, 250);
});
</script>
</body>
</html>

[I converted the jQuery object to a DOM object using [0] as jQuery's css('color') method returns a colour in rgb(). I'll leave it as an exercise if you want to fully convert to jQuery code. It is not integral to this tutorial.]

A similar approach can be taken with different events, just adjust the response time (250ms). Remember though, that if the event is fired rapidly in succession, only the last event will be responded to.

There are plugins for this feature, particularly jQuery versions, that give more control/options and allow you to inject your functions/events into a debounce() (or similarly named) method.

Is This A Good Question/Topic? 1
  • +

Page 1 of 1