JS Guide
HomeQuestionsTopicsCompaniesResources
BookmarksSearch

Built for developers preparing for JavaScript, React & TypeScript interviews.

ResourcesQuestionsSupport
HomeQuestionsSearchProgress
HomeTopicsjavascriptDebounce & Throttle
PrevNext
javascript
intermediate
10 min read

Debounce & Throttle

closures
debounce
events
performance
raf
throttle

Debounce delays execution until a pause in events, while throttle limits execution to a fixed interval — both are essential for controlling high-frequency event handlers.

Key Points

1Debounce

Delays execution until N ms after the last event — resets the timer on each new call. Executes once when events stop. Used for search, auto-save, resize.

2Throttle

Executes at most once per N ms interval during continuous events. Provides consistent, evenly-spaced calls. Used for scroll, drag, rate-limiting.

3Leading vs Trailing Edge

Leading executes on first call immediately; trailing executes after the delay. Libraries like Lodash support both options.

4Implementation Pattern

Both use closures to store timer state and setTimeout for delay — debounce clears the previous timer, throttle blocks calls until the interval passes.

5requestAnimationFrame Alternative

For visual updates, rAF is better than setTimeout-based throttle — it syncs with the browser's repaint cycle for smooth 60fps animations.

What You'll Learn

  • Explain debounce and throttle and when to use each
  • Implement both patterns from scratch using closures and setTimeout
  • Know the difference between leading and trailing edge execution

Deep Dive

High-frequency events like scroll, resize, input, and mousemove can fire hundreds of times per second. Without rate-limiting, expensive operations (DOM updates, API calls, calculations) attached to these events cause performance problems. Debounce and throttle are the two standard patterns for controlling execution frequency.

Debounce

Debounce delays execution until a specified period of inactivity. Every time the event fires, the timer resets. The function only executes once the events stop coming for the specified duration. Think of it as: "Wait until they stop, then execute."

Implementation: The debounce wrapper uses a closure to hold a timeoutId. On each call, it clears the previous timeout with clearTimeout and sets a new one. Only when the delay elapses without another call does the function actually execute.

Use cases: search input autocomplete (wait for the user to stop typing before querying the API), window resize handlers (recalculate layout once resizing is done), form auto-save (save after the user stops editing), and input validation (validate after typing pauses).

Throttle

Throttle ensures a function executes at most once per specified time interval, regardless of how many times the event fires. It provides consistent, evenly-spaced executions. Think of it as: "Execute at regular intervals, no matter what."

Implementation: The throttle wrapper uses a closure to track whether the function is "cooling down." On the first call, it executes immediately and sets a flag. Subsequent calls during the cooldown period are ignored. After the interval passes, the next call is allowed through.

Use cases: scroll event handlers (update position indicator at regular intervals), drag-and-drop tracking (report position consistently), rate-limiting API calls (send analytics at most once per second), and game loop inputs (consistent frame-rate updates).

Leading vs Trailing Edge

Both patterns support leading and trailing edge variants:

  • Trailing (default for debounce): Executes after the delay/interval. The user gets a response after they stop or after the interval.
  • Leading: Executes immediately on the first call, then ignores subsequent calls during the cooldown. The user gets immediate feedback.
  • Both: Executes on both the leading and trailing edge — useful when you want instant response AND the final value.

Libraries like Lodash provide leading and trailing options for both _.debounce and _.throttle.

requestAnimationFrame as Throttle Alternative

For visual updates (animations, scroll effects, layout recalculations), requestAnimationFrame is often better than setTimeout-based throttle. It synchronizes with the browser's repaint cycle (~60fps), ensuring smooth animations. Pattern: store a flag, call requestAnimationFrame, execute the work inside the callback, then reset the flag.

When to Choose Which

  • Need the final value after activity stops? → Debounce (search, auto-save, resize)
  • Need regular updates during continuous activity? → Throttle (scroll, drag, rate-limiting)
  • Need smooth visual updates? → requestAnimationFrame (animations, scroll effects)

Key Interview Distinction

Debounce collapses many events into one execution at the end. Throttle guarantees consistent execution at fixed intervals. Both use closures and setTimeout internally. The choice depends on whether you care about the final result (debounce) or need ongoing feedback (throttle). Being able to implement both from scratch is a common interview coding challenge.

Fun Fact

The terms debounce and throttle come from electronics and mechanical engineering respectively — debounce prevents a physical switch from registering multiple contacts when pressed once (contact bounce), and throttle valves control fluid flow rate in engines.

Learn These First

Closures

intermediate

Continue Learning

Closures

intermediate

Events

beginner

Practice What You Learned

How do debounce and throttle work, and when would you use each?
mid
debounce-throttle
Debounce delays execution until a pause in activity (e.g., wait 300ms after the user stops typing). Throttle limits execution to at most once per time interval (e.g., at most once every 200ms during scrolling). Both are used to control how often expensive functions run.
How would you implement a debounce function from scratch with advanced features?
senior
debounce-throttle
A debounce function delays execution until a pause in calls, using a closure to manage a timer that resets on each invocation. Advanced implementations support leading/trailing edge execution, cancel and flush methods, and a maxWait option to guarantee eventual execution.
Previous
Currying & Partial Application
Next
Prototypes & Inheritance
PrevNext