Debounce vs Throttle in JavaScript – Visual Guide with Code & Timers
JavaScript is an event-driven language, which makes it perfect for building dynamic web interfaces. But with great power comes great responsibility—overusing event handlers, especially on high-frequency events like scroll or resize, can lead to performance issues. This is where debounce and throttle come in.
In this guide, you’ll learn:
- What debounce and throttle are
- How they work under the hood
- When to use each
- Real code examples with timers
- Performance tips and visual cues
1. The Problem: High-Frequency Events
Suppose you want to show the current scroll position on the page. You attach an event listener like this:
window.addEventListener('scroll', () => {
console.log('Scroll position:', window.scrollY);
});
Seems fine, right? But every tiny pixel scroll triggers this function—potentially hundreds of times per second. This is inefficient and can crash a low-performance device.
That’s where debounce and throttle shine. Let’s dig into each approach.
2. Debounce: Delaying Execution Until Things Settle
Debounce ensures a function is called only after a certain period of inactivity. Perfect for search inputs or textboxes where you want to wait until the user stops typing.
function debounce(func, delay) {
let timeout;
return function(...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), delay);
};
}
How It Works: Each time the event fires, the previous timeout is cleared and a new one is set. The function only runs after the delay if no other event re-triggers it.
Example usage on keypress:
const logInput = debounce((val) => console.log('Input:', val), 300);
document.getElementById('search').addEventListener('input', (e) => {
logInput(e.target.value);
});
This waits 300ms after the user stops typing before logging the input.
3. Throttle: Limiting Frequent Execution
Throttle ensures a function is called at most once every set number of milliseconds, no matter how many times the event is triggered. This is ideal for scroll, resize, or mouse movement.
function throttle(func, interval) {
let lastTime = 0;
return function(...args) {
const now = Date.now();
if (now - lastTime >= interval) {
lastTime = now;
func.apply(this, args);
}
};
}
How It Works: A timestamp records the last execution. If enough time has passed since then, the function runs again.
Example usage on scroll:
const logScroll = throttle(() => console.log('Scroll Y:', window.scrollY), 100);
window.addEventListener('scroll', logScroll);
This will log the scroll position at most once every 100ms no matter how fast the user scrolls.
4. Visualizing Debounce and Throttle with Timers
Let’s create a visual playground using buttons and timers to simulate frequent function calls.
// HTML Setup
<button id="debounceBtn">Click Rapidly (Debounce)</button>
<button id="throttleBtn">Click Rapidly (Throttle)</button>
<div id="counter"></div>
// JavaScript
let count = 0;
const updateCounter = () => {
count++;
document.getElementById('counter').innerText = `Triggered: ${count}`;
};
const debounceClick = debounce(updateCounter, 1000);
const throttleClick = throttle(updateCounter, 1000);
document.getElementById('debounceBtn').addEventListener('click', debounceClick);
document.getElementById('throttleBtn').addEventListener('click', throttleClick);
Try rapidly clicking the buttons. The debounce button waits a full 1 second of inactivity; the throttle one counts evenly every second.
5. When to Use What
- 🟢 Use debounce for inputs: text search, resizing window after user stops adjusting.
- 🟢 Use throttle for observation: scroll position, real-time analytics, game loops.
In general:
- Debounce = Respond after the burst
- Throttle = Respond during the burst but in controlled intervals
And remember: too much event handling = janky UI!
6. Performance Tips & Libraries
Instead of reinventing the wheel in production, consider using a stable utility:
- Lodash:
_.debounceand_.throttle - RxJS: great for stream-based event management
Also consider:
- Detaching observers and listeners on unmount or destruction
- Avoiding accidental anonymous functions in event callbacks
- Profiling your scripts using Chrome DevTools
Conclusion
Debounce and throttle are essential tools for every JavaScript developer. Whether you’re improving UI performance or designing real-time feedback systems, knowing which one to use and how can drastically improve user experience and app efficiency.
Happy coding 🔁
Useful links:


