What Is debounceTime?
The debounceTime operator postpones each value emitted by a source until the specified due time has elapsed. If a newer value arrives before that time is up, the previously pending value is discarded and the countdown restarts. Consequently, debounceTime effectively holds onto the latest value in a sequence and only releases it once the source has been quiet for the configured duration.
Operationally, the flow is as follows:
- Upon receiving a new value, a fresh timer is set.
- The incoming value is stored, and any prior stored value is replaced.
- When the timer expires, the stored value is emitted downstream.
- If another value shows up before the timer finishes, the process repeats from step 1.
By default, the scheduler behind this operator relies on setInterval via AsyncScheduler to handle timing internally.
When to Use It
This operator shines for event streams that fire dozens or even hundreds of times per second. Typical use cases involve browser events like scrolling, pointer moves, or keystrokes. What matters in most of these situations is the final snapshot: where the page stands once the user halts scrolling, what the search box contains after typing pauses, and so forth. By collapsing a rapid succession of occurrences into a single notification, debounceTime lets you reduce the number of callbacks and thereby enhance overall responsiveness.
Common events that benefit from debouncing are resize, scroll, and keyup/keydown. You should also wrap any interaction that leads to heavy computation or repeat API requests with this operator.
The snippet below demonstrates applying debounceTime to an input field:
const inputElement = document.createElement('input');
document.body.appendChild(inputElement);
fromEvent(inputElement, 'input')
.pipe(
debounceTime(500),
map((event: any) => event.target.value)
).subscribe(val => console.log(val));
Experiment
More Reading
- Official documentation
- How to debounce an input while skipping the first entry
- Rx.js Operators, Part II
