Deboucing
March 06, 2020
2 min read
The goal behind debouncing is to reduce the overhead by preventing a function from being called several times in succession. It is achieved by introducing a delay using setTimeout
function.
const DELAY = 500; // ms
function searchData() {
const searchInput = document.getElementById('search').value;
if (searchInput) {
// Call to search API
console.log('Searching for...', searchInput);
}
}
// Return an anomymous function that has access to the `fn`
// argument of our `debounce` method through closures.
function debounce(fn, delay) {
let timer;
return function () {
// Assign `this` to a variable named `context` so that the `fn` argument
// passed to our `debounce` method can be called in the proper context.
const context = this;
// Assign `arguments` to `args`, allows us to combine all arguments passed
// in the `fn` argument of our `debounce` method in a single variable.
const args = arguments;
if (timer) {
// As long as the event that our `debounce` method is bound to is still firing
// within the `wait` period, remove the numerical ID (returned from `setTimeout`)
// from JavaScript's execution queue. This prevents the function passed in the
// `setTimeout` function from being invoked.
clearTimeout(timer);
}
timer = setTimeout(() => {
// `apply` method allows us to call a function in an explicit context.
fn.apply(context, args);
}, delay);
};
}
const efficientSearchData = debounce(searchData, DELAY);
// ES6
const debounce = (func, delay) => {
let timer;
return (...args) => {
const next = () => func(args);
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(next, delay > 0 ? delay : DELAY);
};
};
Test
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Test Debouce</title>
</head>
<body>
<input type="text" oninput="efficientSearchData()" id="search" />
<script src="./debounce.js"></script>
</body>
</html>
With deboucing, the searchData
function would be called only when the delay between two successive oninput
events is at least 500ms.