Understanding sampleTime

sampleTime introduces a delay before forwarding values from a source observable to the observer, adhering to a specified duration. It shares similarities with debounceTime in managing emission frequency, but it operates differently: sampleTime ensures a steady, regular emission pattern that never exceeds the set interval, rather than simply postponing each value.

This operator behaves much like throttleTime configured with {leading: false, trailing: true}. Yet, there are two primary distinctions to note:

  • sampleTime continuously resets its timer regardless of whether the source emits new values, whereas throttleTime only reinitiates its timer when a fresh value arrives. This can lead to performance trade-offs, making auditTime a more efficient choice for rate-limiting scenarios.
  • When the source completes before the interval elapses, throttleTime still delivers the pending value, but sampleTime drops it entirely.

The operational flow of sampleTime is as follows:

  1. Start a new interval.
  2. On each incoming value, store it and replace any previously held value.
  3. When the interval finishes, output the stored value to the observer.
  4. Begin a fresh interval.
  5. If the source completes before the interval ends, abandon the stored value.

Under the hood, this operator leverages setInterval via the AsyncScheduler for its timing mechanism by default.

Practical Applications

sampleTime is ideal when you need to ignore a stream of values for a fixed period. It shines in handling events that fire at extremely high rates, such as scroll actions, window resizing, mouse movement, or typing in a field.

Consider a scroll listener attached to a page: scrolling to a depth of, say, 5000px can easily trigger over a hundred events. If the handler does heavy lifting—like complex calculations or DOM updates—this can lead to visible lag. By throttling the handler’s execution rate, you can significantly boost performance without sacrificing the user experience.

It’s also wise to apply throttling to any interaction that might trigger excessive computations or network requests.

The following example demonstrates applying sampleTime to an input field:

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

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

Try It Out

Further Reading