- Published on
Debounce and throttle are two common techniques to rate limit something. I see debounce very often in FE apps. For example, if you run some validation code on every keydown event for a text input, it often makes more sense to debounce it so it runs at the 'end' of all typing (and only once) instead of for each key press.
Table of Contents
What is debounce
Debounce is a way to execute some code only once, even if lots of event triggers are fired at around the same time.
e.g. if i have a function like this:
/*
<html><input id="id1"/></html>
*/
const someInputField = document.getElementById('id1');
function isValidString(s) {
return s.length > 5
}
function validateInput() {
if(!isValidString(someInputField.value)) {
// this is a very bad practive, just for illustration...
alert('you have an error!')
}
}
someInputField.addEventListener('keydown', validateInput)
then it could trigger an alert on every keydown.
But lets wrap it in debounce, and it will get triggered after the user stops firing lots of keydown
events.
It is very simple to do:
- Create a function called
debounce
that takes afn
argument (to be called later), and a min delay - get a
timeoutId
variable (initiallyundefined
) - then return a function in that function that:
- clears any existing timeout for this debounced function
- then add a
setTimeout()
to run thefn()
after a delay. - If the debounced function is called again, it resets the timer.
function debounce(fn, delayInMs = 100) {
let timeoutId;
return function() {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
fn()
}, delayInMs);
}
}
const debouncedValidateInput = debounce(validateInput, 100);
// someInputField.removeEventListener('keydown', validateInput)
someInputField.addEventListener('keydown', debouncedValidateInput)
This will make it feel more natural and more usable than seeing tons of alert()
s.
How to easily use debounce
I'd recommend lodash...
import {debounce} from 'lodash';
const debouncedFunction = debounce(myFunction, 250);
What is throttle
Throttling is a technique to ensure some code immediately, but then won't allow it to be run again until a period of time.
Example of throttle:
function throttle (fn, delayInMs) {
let canRunNow = true;
return () => {
if (canRunNow) {
fn()
canRunNow = false;
setTimeout(() => {
canRunNow = true;
}, delayInMs);
}
}
}
Now it will run immediately, but then not again until delayInMs
...
What is the difference between debounce and throttle?
- Debounce to delay the first run until X time has passed and no other calls to run it
- Throttle to run immediately, then don't run again until X time has passed