Debouncing & Throttling
Debouncing and throttling limit how often a function runs — essential for performance-sensitive events like scroll, resize, and input. Debounce waits until user stops. Throttle runs at fixed intervals.
Debounce & Throttle
- Debounce — Waits X ms after LAST call before executing. Resets if called again. Used for: search input, form auto-save, resize handler
- Throttle — Executes at most once every X ms. Ignores extra calls. Used for: scroll events, mouse move, API rate limiting
- Difference — Debounce: fires AFTER activity stops. Throttle: fires DURING activity at intervals
- Without these — resize fires 100+/sec, scroll fires 60+/sec. Each fires expensive functions. Performance disaster
Debounce & Throttle Code
// Debounce — wait until user stops
function debounce(fn, delay) {
let timeoutId;
return function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn.apply(this, args), delay);
};
}
// Usage: search input — only search after user stops typing for 300ms
const search = debounce((query) => {
console.log(`🔍 Searching: ${query}`);
}, 300);
search("H"); // cancelled
search("He"); // cancelled
search("Hel"); // cancelled
search("Hello"); // ✅ executes after 300ms
// Throttle — max once per interval
function throttle(fn, limit) {
let inThrottle = false;
return function(...args) {
if (!inThrottle) {
fn.apply(this, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
// Usage: scroll — update at most every 100ms
const handleScroll = throttle(() => {
console.log("📜 Scroll position updated");
}, 100);
// window.addEventListener("scroll", handleScroll);
// Auto-save with debounce
const autoSave = debounce((content) => {
console.log("💾 Auto-saving:", content.slice(0, 30) + "...");
// saveToServer(content);
}, 1000);
// Simulating typing
["D", "Dr", "Dra", "Draf", "Draft"].forEach((text, i) => {
setTimeout(() => autoSave(text), i * 200);
});
// Only saves ONCE with "Draft" after user stops typingTip
Tip
Debounce search inputs (300ms delay). Throttle scroll handlers (100ms intervals). These two techniques alone can eliminate 90% of common performance issues in web applications.
Measure first! Code split, tree shake.
Common Mistake
Warning
Applying debounce/throttle to the wrong function. Debounce the handler, not the event listener. Wrong: el.addEventListener('input', debounce(handler, 300)()) — calls immediately. Right: el.addEventListener('input', debounce(handler, 300)).
Practice Task
Note
Optimization practice: (1) Build a search input with 300ms debounce. (2) Create a scroll handler with 100ms throttle. (3) Compare the number of function calls with and without optimization.
Quick Quiz
Key Takeaways
- Debouncing and throttling limit how often a function runs — essential for performance-sensitive events like scroll, resize, and input.
- Debounce — Waits X ms after LAST call before executing. Resets if called again. Used for: search input, form auto-save, resize handler
- Throttle — Executes at most once every X ms. Ignores extra calls. Used for: scroll events, mouse move, API rate limiting
- Difference — Debounce: fires AFTER activity stops. Throttle: fires DURING activity at intervals