I am currently learning debounce in Javascript and I came across two ways of writing debounce functions that works the same. One is a lot simpler like regular function, the other one is the complicated one that everyone seems to use.
<input type="text" oninput="betterFunction()">
<script>
function getData() {
console.log('Data Fetched')
}
function debounce(callback, delay) {
let timer
return function() {
clearTimeout(timer)
timer = setTimeout(() => {
callback();
}, delay)
}
}
const betterFunction = debounce(getData, 1000)
</script>
<input type="text" oninput="debounce()">
<script>
let timer
function debounce() {
clearTimeout(timer)
timer = setTimeout(() => {
console.log('Data Fetched');
}, 1000)
}
</script>
What is the difference between these two ways of debouncing if they both gives the same result? PS: I am surprised that I have never seen anyone use the 'version 2', ofcourse something must me wrong. Could anybody explain the differences please?
Version 1 is better, because it:
timer
(timeout ID) within the scope of—the lifetime of—the function callJosh W Comeau has an informative article covering debounce.
Here is his (modified) minimal version:
const debounce = (callback, wait) => {
let timeoutId = null;
return (...args) => {
window.clearTimeout(timeoutId);
timeoutId = window.setTimeout(() => {
callback(...args);
}, wait);
};
}
Note: I replaced the callback.apply(null, args)
with the more succinct callback(...args)
const handleMouseMove = debounce((mouseEvent) => {
// Do stuff with the event!
}, 250);
document.addEventListener('mousemove', handleMouseMove); // Add listener
document.removeEventListener('mousemove', handleMouseMove); // Remove listener
In the snippet below, points are drawn every time the user stops moving the mouse after 250ms. Each point is auto-removed after 2 seconds.
const debounce = (callback, wait) => {
let timeoutId = null;
return (...args) => {
window.clearTimeout(timeoutId);
timeoutId = window.setTimeout(() => {
callback(...args);
}, wait);
};
}
const createPoint = (x, y, color) => {
const point = Object.assign(document.createElement('div'), { className: 'point' });
Object.assign(point.style, { top: `${y - 2}px`, left: `${x - 2}px`, background: color });
document.body.append(point);
return point;
};
// Log mouse coordinates when user stops moving mouse after 250ms
const handleMouseMove = debounce(({ clientX: x, clientY: y }) => {
console.log(`Creating MOVE point at: (${x}, ${y})`);
const point = createPoint(x, y, 'white');
// Auto-remove after 1 second
setTimeout(() => {
console.log(`Removing MOVE point at: (${x}, ${y})`);
point.remove();
}, 2000);
}, 250);
// Log mouse coordinates when user stops clicking 250ms
const handleClick = debounce(({ clientX: x, clientY: y }) => {
console.log(`Creating CLICK point at: (${x}, ${y})`);
const point = createPoint(x, y, 'red');
// Auto-remove after 1 second
setTimeout(() => {
console.log(`Removing CLICK point at: (${x}, ${y})`);
point.remove();
}, 2000);
}, 250);
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('click', handleClick);
.as-console-wrapper { max-height: 5em !important; }
html, body { width: 100%; height: 100%; margin: 0; padding: 0; }
body { background: #222; position: relative; }
.point { position: absolute; width: 4px; height: 4px; border-radius: 50%; background: #FFF; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With