JavaScript Debounce & Throttle Patterns Quiz

JavaScript
0 Passed
0% acceptance

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.

35 Questions
~70 minutes
1

Question 1

What defines debouncing?

A
Delaying execution until a burst of calls stops for a specified wait period
B
Running code immediately and then ignoring further calls
C
Executing once per animation frame
D
Splitting work across workers
2

Question 2

Why is debouncing ideal for text input validation?

A
It waits until typing pauses, avoiding API calls on every keystroke
B
It prevents the handler from ever running
C
It requires no timer
D
It only works for scroll events
3

Question 3

What prints?

javascript
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)
A
b then c
B
a, b, c
C
Only c
D
Only b
4

Question 4

How does wait duration affect debounce behavior?

A
Longer waits increase responsiveness but reduce API calls
B
Shorter waits reduce perceived latency but risk more triggers
C
Both statements are true depending on requirements
D
Wait duration has no impact
5

Question 5

What prints?

javascript
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))
A
3 only
B
2 then 3
C
1 then 2 then 3
D
Throws TypeError
6

Question 6

What defines throttling?

A
Ensuring a function executes at most once per interval regardless of input frequency
B
Delaying until inactivity ends
C
Batching promises
D
Caching results
7

Question 7

What prints?

javascript
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)
A
a then c
B
a then b then c
C
a only
D
c only
8

Question 8

Why do throttled scroll handlers often use 16ms waits?

A
16ms matches 60fps frame timing, aligning updates with the rendering budget
B
Browsers require 16ms minimum
C
It guarantees no dropped frames regardless of work
D
It is the default for setTimeout
9

Question 9

What does leading: true configure in a debounce or throttle helper?

A
Invoke immediately on the first call, before waiting for the interval
B
Invoke only after the interval
C
Disable timers entirely
D
Force promise returns
10

Question 10

What prints?

javascript
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)
A
first then third
B
first, second, third
C
second then third
D
third only
11

Question 11

Why combine leading true with trailing true?

A
To get immediate feedback plus a final update carrying the latest value after activity stops
B
So the handler runs twice per millisecond
C
To guarantee equal spacing
D
To disable wait time
12

Question 12

What prints?

javascript
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)
A
1 then 3
B
1 then 2 then 3
C
Only 1
D
Only 3
13

Question 13

Why is throttling mousemove handlers helpful during drag operations?

A
It limits heavy calculations (e.g., layout) to a sustainable cadence while still showing movement
B
It pauses dragging entirely
C
It replaces requestAnimationFrame
D
It prevents pointer events from firing
14

Question 14

Which pattern suits infinite scroll pagination triggered near the bottom of the viewport?

A
Debounce, so loading waits until the user pauses near the threshold
B
Throttle, so loading fires every frame
C
Neither; manual loops only
D
SetInterval with 0 wait
15

Question 15

What prints?

javascript
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)
A
saved hell only
B
saved h, saved he, saved hel, saved hell
C
saved hel only
D
Nothing logs
16

Question 16

Why is throttling preferable for scroll spy indicators?

A
The position can update regularly while the user scrolls without waiting for a pause, keeping indicators in sync
B
You want the indicator to jump after long delays
C
Throttling prevents directional changes
D
Debouncing would update faster
17

Question 17

What prints?

javascript
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)
A
cancelled then AB
B
AB only
C
cancelled only
D
Throws due to pending undefined
18

Question 18

Why return a cancel() handle from debounce utilities?

A
It lets you flush or clear pending work when components unmount, preventing stale API calls
B
It makes debounce synchronous
C
It doubles timer usage
D
It is required by browsers
19

Question 19

What prints?

javascript
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)
A
2 then 3
B
1 then 2 then 3
C
1 then 3
D
2 only
20

Question 20

Why might a throttled handler connect to passive listeners?

A
Passive listeners guarantee scroll performance by disallowing preventDefault, so throttled logic cannot accidentally block scrolling
B
Passive equals debounce
C
Passive cancels throttling
D
Passive automatically queues trailing calls
21

Question 21

What prints?

javascript
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)
A
a then c
B
a then b then c
C
a only
D
b then c
22

Question 22

Why can using Date.now() for throttle timestamps drift if the page sleeps?

A
Tab suspension pauses timers; when the tab resumes, the elapsed time may exceed wait immediately, causing burst execution
B
Date.now() returns random numbers
C
Timers never resume
D
It only affects debounce
23

Question 23

How do long-running handlers break throttling intent?

A
If the handler itself takes longer than the wait, events queue up and the user still sees jank—throttle controls call frequency, not execution cost
B
Long handlers speed everything up
C
Throttling cancels long handlers automatically
D
It has no effect
24

Question 24

What prints?

javascript
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)
A
tick roughly every 50ms until interval stops
B
tick every 10ms
C
tick never logs
D
tick logs once and throws
25

Question 25

Why does debouncing resize events help chart reflows?

A
Only final viewport dimensions are used to redraw expensive charts, preventing dozens of layout recalculations while the user drags the window
B
Resizing rarely fires events
C
Debounce stops all stretch animations
D
Debounce uses GPU acceleration
26

Question 26

How does throttling limit analytics beacons?

A
It ensures events like scroll depth updates send at most once per interval, reducing bandwidth and server load
B
It increases beacon frequency
C
It removes the need for batching
D
It disables event listeners
27

Question 27

What prints?

javascript
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)
A
undefined
B
Save
C
Throws due to this binding
D
Debounce returns immediately
28

Question 28

How can you preserve this in debounce wrappers?

A
Capture context with const context = this and apply fn using context inside the timeout, or bind fn ahead of time
B
Use eval
C
Avoid setTimeout entirely
D
Debounce cannot retain context
29

Question 29

What prints?

javascript
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)
A
1 then 3
B
1 then 2
C
1 only
D
2 only
30

Question 30

Why can using setInterval for throttling be problematic?

A
If work inside takes longer than interval, calls pile up or overlap; throttling should be based on actual completion time
B
setInterval is deprecated
C
setInterval always throttles automatically
D
setInterval cannot be cleared
31

Question 31

What prints?

javascript
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)
A
start then late, pending: undefined (bug: stored args never used)
B
start, mid, late
C
start only, pending: ["mid"]
D
mid then late
32

Question 32

How do you flush a debounced function immediately?

A
Expose a flush() method that clears the timer and invokes the callback right away if pending
B
Set wait to 0 only
C
Call clearTimeout with no timer
D
Use setInterval
33

Question 33

Why might you avoid arrow functions when defining debounce wrappers inside classes?

A
Arrow functions capture surrounding this; if rebound per instance you may create a new debounce wrapper on each render instead of reusing one
B
Arrow functions break setTimeout
C
Arrow functions cannot close over timers
D
Arrows disable leading mode
34

Question 34

Which pattern helps minimize CPU usage when syncing scroll state to localStorage?

A
Debounce, so writing happens after scrolling stops instead of every tick
B
Throttle, to write constantly
C
Both patterns disable localStorage
D
setInterval at 5ms
35

Question 35

Why document your debounce/throttle choices for teammates?

A
Future engineers need to know why certain UI interactions intentionally lag or skip events, preventing accidental removal of critical performance safeguards
B
Documentation disables timers
C
It enforces leading mode
D
It satisfies TypeScript

QUIZZES IN JavaScript