Photo by Chris Liverani on Unsplash

Debounce vs Throttle vs Queue execution

We have loads of articles on the internet explaining what Debouncing, Throttling are and what the difference between them is. But most i found were often long, confusing and with complicated code examples (if any).

So i have come up with simplified working code examples for them to get the concept in a jiffy. Lets start with the easier one, Debounce.


Debounce

Debouncing a function comes in handy when it is being called continuously and we want it to execute after a certain period if time has passed since the last call.

This comes in handy in cases where we want the situation to stabilise before calling the handler in order to improve performance. One of the best examples of debounce i found was in this blog by Jhey Tompkins

For debouncing, we could have some auto save feature in our application. With auto save on the application tries to save the state of our application every time the user makes an update or has some interaction. It waits 5 seconds to make sure no other updates or interactions are made before saving the state else it records the new state and repeats the process. If any interaction happens it resets its timer for 5 seconds again.

function debounce(func, waitTime) {
var timeout;

return function () {
clearTimeout(timeout);
timeout = setTimeout(func, waitTime);
};
};

Thats it, thats how simple debounce can be.

Throttle

This technique is more aptly named. Throttling a function comes in handy when it is being called continuously and we want it to execute once every x seconds. A good example of this would be a scroll handler or a resize handler, where we want to execute the handler once in a fixed time period even if the function is getting called continuously.

function throttle(func, waitTime) {
var timeout = null;
var previous = 0;

var later = function () {
previous = Date.now();
timeout = null;
func();
};

return function () {
var now = Date.now();
var remaining = waitTime - (now - previous);
        if (remaining <= 0 || remaining > waitTime) {
if (timeout) {
clearTimeout(timeout);
}
later();
} else if (!timeout){ //null timeout -> no pending execution

timeout = setTimeout(later, remaining);
}
};
};

Extra: Queueing

On the lines of debounce and throttle, function calls can be queued also. In this the function is executed the number of times it is called but there is a fixed wait time before each execution. It came in handy recently for me when i was using a library and ran into a bug calling a function in it multiple times without a delay was causing an issue. (there can be other use cases too :) )

function queue(func, waitTime) { 
var funcQueue = [];
var isWaiting;

var executeFunc = function (params) {
isWaiting = true;
func(params);
setTimeout(play, waitTime);
};

var play = function () {
isWaiting = false;
if (funcQueue.length) {
var params = funcQueue.shift();
executeFunc(params);
}
};

return function (params) {
if (isWaiting) {
funcQueue.push(params);
} else {
executeFunc(params);
}
}
};

To conclude

Before you decide on an optimisation technique, take a step back and think which one will give the best result for that case. There is always one which will be more performant.

Please feel free to leave a response or tweet me with any questions or suggestions.