Understanding auditTime

auditTime postpones each value emitted by a source observable until the specified duration has elapsed. This operator, much like debounceTime, serves to regulate the frequency at which values are delivered to an observer. However, auditTime differs in that it ensures emissions occur at steady intervals, never exceeding the configured cadence.

The behavior of auditTime closely mirrors that of throttleTime when configured with {leading: false, trailing: true}. The key distinction lies in how the final value is managed: if the source observable finishes prematurely, throttleTime will still forward the pending value, whereas auditTime will drop it entirely.

The operator executes through these steps:

  • upon receiving a new value, initiates a fresh interval
  • stores the most recent value
  • if another value arrives within the interval, retains it and replaces the stored one
  • when the interval concludes, forwards the stored value to the observer
  • if the source completes before the interval finishes, the stored value is discarded

Internally, the operator leverages setInterval via AsyncScheduler for scheduling purposes.

Practical applications

When the goal is to skip values originating from a source observable during a defined timeframe, auditTime proves invaluable. It finds its primary use for events firing dozens or even hundreds of times each second. Common candidates include DOM events such as scrolling, window resizing, mouse tracking, and typing.

Consider attaching a scroll listener to a page element and scrolling to about 5000px; this action typically triggers over a hundred events. When the corresponding handler carries out heavy operations like complex computations or DOM modifications, you might encounter responsiveness issues known as jank. Capping the frequency at which such a handler executes, without compromising user interaction quality, can dramatically improve performance.

Moreover, it's wise to apply throttling to any interaction that results in substantial computational load or numerous API requests.

Below demonstrates applying auditTime to an input field:

const inputElement = document.createElement('input');
document.body.appendChild(inputElement);

fromEvent(inputElement, 'input')
   .pipe(
       auditTime(500),
       map((event: any) => event.target.value)
   ).subscribe(val => console.log(val));

Interactive example

Further reading