JavaScript Debounce & Throttle Patterns Quiz
Answer 35 questions covering debounce timing, throttle intervals, leading/trailing triggers, preventing noisy events, scroll/input use cases, manual implementations, pitfalls, and UI performance gains.
Question 1
What defines debouncing?
Question 2
Why is debouncing ideal for text input validation?
Question 3
What prints?
const debounce = (fn, wait) => {
let timer
return (...args) => {
clearTimeout(timer)
timer = setTimeout(() => fn(...args), wait)
}
}
const log = debounce((value) => console.log(value), 100)
log('a')
log('b')
setTimeout(() => log('c'), 150)
Question 4
How does wait duration affect debounce behavior?
Question 5
What prints?
const debounce = (fn, wait) => {
let timer
return (...args) => {
clearTimeout(timer)
timer = setTimeout(() => fn(...args), wait)
}
}
const log = debounce((value) => console.log(value), 0)
log(1)
log(2)
Promise.resolve().then(() => log(3))
Question 6
What defines throttling?
Question 7
What prints?
const throttle = (fn, wait) => {
let last = 0
return (...args) => {
const now = Date.now()
if (now - last >= wait) {
last = now
fn(...args)
}
}
}
const log = throttle((value) => console.log(value), 100)
log('a')
setTimeout(() => log('b'), 50)
setTimeout(() => log('c'), 120)
Question 8
Why do throttled scroll handlers often use 16ms waits?
Question 9
What does leading: true configure in a debounce or throttle helper?
Question 10
What prints?
const debounce = (fn, wait, { leading = false, trailing = true } = {}) => {
let timer
return (...args) => {
const callNow = leading && !timer
clearTimeout(timer)
timer = setTimeout(() => {
timer = null
if (trailing && !callNow) fn(...args)
}, wait)
if (callNow) fn(...args)
}
}
const log = debounce(console.log, 100, { leading: true, trailing: false })
log('first')
log('second')
setTimeout(() => log('third'), 150)
Question 11
Why combine leading true with trailing true?
Question 12
What prints?
const throttle = (fn, wait, { trailing = true } = {}) => {
let last = 0
let timer
let lastArgs
return (...args) => {
const now = Date.now()
if (!last) last = now
const remaining = wait - (now - last)
lastArgs = args
if (remaining <= 0) {
clearTimeout(timer)
timer = null
last = now
fn(...args)
} else if (!timer && trailing) {
timer = setTimeout(() => {
last = Date.now()
timer = null
fn(...lastArgs)
}, remaining)
}
}
}
const log = throttle((value) => console.log(value), 100)
log(1)
setTimeout(() => log(2), 40)
setTimeout(() => log(3), 80)
Question 13
Why is throttling mousemove handlers helpful during drag operations?
Question 14
Which pattern suits infinite scroll pagination triggered near the bottom of the viewport?
Question 15
What prints?
const debounce = (fn, wait) => {
let timer
return (...args) => {
clearTimeout(timer)
timer = setTimeout(() => fn(...args), wait)
}
}
const saveDraft = debounce((text) => console.log('saved', text), 200)
saveDraft('h')
setTimeout(() => saveDraft('he'), 100)
setTimeout(() => saveDraft('hel'), 150)
setTimeout(() => saveDraft('hell'), 350)
Question 16
Why is throttling preferable for scroll spy indicators?
Question 17
What prints?
function debouncePromise(fn, wait) {
let timer
let pending
return (...args) => {
if (pending) pending.reject(new Error('cancelled'))
clearTimeout(timer)
pending = {}
pending.promise = new Promise((resolve, reject) => {
pending.resolve = resolve
pending.reject = reject
})
timer = setTimeout(() => {
Promise.resolve(fn(...args))
.then(pending.resolve)
.catch(pending.reject)
pending = null
}, wait)
return pending.promise
}
}
const search = debouncePromise((query) => query.toUpperCase(), 50)
search('a').catch((error) => console.log(error.message))
setTimeout(() => search('ab').then(console.log), 30)
Question 18
Why return a cancel() handle from debounce utilities?
Question 19
What prints?
const throttleRAF = (fn) => {
let scheduled = false
let lastArgs
return (...args) => {
lastArgs = args
if (scheduled) return
scheduled = true
requestAnimationFrame(() => {
scheduled = false
fn(...lastArgs)
})
}
}
const log = throttleRAF((value) => console.log(value))
log(1)
log(2)
setTimeout(() => log(3), 20)
Question 20
Why might a throttled handler connect to passive listeners?
Question 21
What prints?
const throttle = (fn, wait) => {
let timer
return (...args) => {
if (timer) return
timer = setTimeout(() => {
timer = null
}, wait)
fn(...args)
}
}
const log = throttle(console.log, 100)
log('a')
setTimeout(() => log('b'), 50)
setTimeout(() => log('c'), 200)
Question 22
Why can using Date.now() for throttle timestamps drift if the page sleeps?
Question 23
How do long-running handlers break throttling intent?
Question 24
What prints?
const measure = (fn, wait, totalCalls) => {
const throttled = fn(wait)
let count = 0
const interval = setInterval(() => {
throttled(++count)
if (count === totalCalls) clearInterval(interval)
}, 10)
}
measure((wait) => throttle(() => console.log('tick'), wait), 50, 6)
Question 25
Why does debouncing resize events help chart reflows?
Question 26
How does throttling limit analytics beacons?
Question 27
What prints?
const debounce = (fn, wait) => {
let timer
return (...args) => {
clearTimeout(timer)
timer = setTimeout(() => fn(...args), wait)
}
}
const handler = debounce(function () {
console.log(this.label)
}, 50)
const button = { label: 'Save' }
handler.call(button)
Question 28
How can you preserve this in debounce wrappers?
Question 29
What prints?
const throttle = (fn, wait, options = {}) => {
let lastTime = 0
let timer
return (...args) => {
const now = Date.now()
const remaining = wait - (now - lastTime)
if (remaining <= 0) {
clearTimeout(timer)
timer = null
lastTime = now
fn(...args)
} else if (!timer && options.trailing !== false) {
timer = setTimeout(() => {
lastTime = Date.now()
timer = null
fn(...args)
}, remaining)
}
}
}
const log = throttle(console.log, 100, { trailing: false })
log(1)
setTimeout(() => log(2), 50)
setTimeout(() => log(3), 120)
Question 30
Why can using setInterval for throttling be problematic?
Question 31
What prints?
const throttle = (fn, wait) => {
let lastTime = 0
let pending
return (...args) => {
const now = Date.now()
if (now - lastTime >= wait) {
lastTime = now
fn(...args)
} else {
pending = args
}
}
}
const log = throttle(console.log, 100)
log('start')
setTimeout(() => log('mid'), 30)
setTimeout(() => log('late'), 120)
setTimeout(() => console.log('pending:', pending), 200)
Question 32
How do you flush a debounced function immediately?
Question 33
Why might you avoid arrow functions when defining debounce wrappers inside classes?
Question 34
Which pattern helps minimize CPU usage when syncing scroll state to localStorage?
Question 35
Why document your debounce/throttle choices for teammates?
