If you have written a search component that returns matching result as you type – you would realise that sending a request to the server on every key press is not required as that can result in burdening the server with too many requests.
A good practice is to throttle your requests to fire on a given amount time. Most users these days can type there name in 1/10 of a second, so 100-250ms is a good amount of delay before sending a request.
Debounce
A JavaScript function written to throttle execution is called a debounce function. Or in another words, it limits the rate at which a function can fire.
Coding a debounce function
Let's start by creating an index.html
and adding an input
field to it for search input.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Throttle function calls</title>
</head>
<body>
<form>
<label>Search</label>
<input type="text" id="search" placeholder="search">
</form>
</body>
</html>
Create a JavaScript file for our debounce function, let's name it throttle.js
.
function debounce(fn, delay) {
var timer = null,
delay = delay || 250;
return function () {
var args = arguments;
clearTimeout(timer);
timer = setTimeout(function() {
fn.apply(this, args);
}.bind(this), delay);
};
}
We can call this function inside an event handler.
var searchBox = document.getElementById('search');
searchBox.onkeyup = debounce(function(event) {
console.log('searching .. ' + searchBox.value);
},
1000
);
The returned function will be able to reference timer
due to closure. Each call to the returned function will share this common timer.
var timer = null,
Calling debounce returns a new anonymous function.
return function () {
clearTimeout
is the basic debounce behaviour where you can call this function several times, but it will only execute once before or after imposing a delay.
Each time the returned function is called, the timer starts over.
clearTimeout(timeout);
Now you can call the original function with apply
. Apply lets you define the this
object as well as the arguments (both captured before setTimeout).
The source code for this post can be found on Github.