JavaScriptMarch 30, 2026
Debounce vs Throttle: When to Use Each
Learn the difference between debounce and throttle and when to use each technique.
Debounce and throttle are essential techniques for optimizing performance. Let’s understand when to use each.
Debounce
Debounce delays execution until after a period of inactivity.
javascript
function debounce(fn, delay) {
let timeoutId
return function (...args) {
clearTimeout(timeoutId)
timeoutId = setTimeout(() => fn.apply(this, args), delay)
}
}
// Usage: Search input
const handleSearch = debounce((query) => {
fetchSearchResults(query)
}, 300)
input.addEventListener('input', (e) => handleSearch(e.target.value))
Use debounce for:
- Search inputs
- Window resize handlers
- Form auto-save
- Button clicks (prevent double-click)
Throttle
Throttle ensures a function executes at most once per time period.
javascript
function throttle(fn, limit) {
let inThrottle
return function (...args) {
if (!inThrottle) {
fn.apply(this, args)
inThrottle = true
setTimeout(() => inThrottle = false, limit)
}
}
}
// Usage: Scroll handler
const handleScroll = throttle(() => {
updateScrollPosition()
}, 100)
window.addEventListener('scroll', handleScroll)
Use throttle for:
- Scroll events
- Mouse move tracking
- Game loop updates
- API rate limiting
Visual Comparison
code
Events: |--x-x-x-x-x-x-x-------x-x-x-x|
Debounce: |------------------------x----|
(Fires after last event + delay)
Throttle: |--x-----x-----x-------x------|
(Fires at regular intervals)
Advanced: Leading & Trailing
javascript
function debounce(fn, delay, { leading = false, trailing = true } = {}) {
let timeoutId
let lastCallTime
return function (...args) {
const now = Date.now()
if (leading && (!lastCallTime || now - lastCallTime > delay)) {
fn.apply(this, args)
lastCallTime = now
}
clearTimeout(timeoutId)
if (trailing) {
timeoutId = setTimeout(() => {
fn.apply(this, args)
lastCallTime = Date.now()
}, delay)
}
}
}