Mastering RxJS Filtering Operators: Complete Guide with Examples

Nandeep Barochiya
9 min readMay 24, 2024

--

In the dynamic world of reactive programming, managing torrents of asynchronous data can be overwhelming. This is where RxJS filtering operators come to the rescue!

These powerful tools help you sift through the noise, extracting only the most relevant information from your data streams, and ensuring your applications remain responsive and efficient. RxJS (Reactive Extensions for JavaScript) offers a comprehensive set of operators for transforming, combining, and filtering data streams. Among these, filtering operators play a crucial role in controlling data flow by allowing only the values that meet specific criteria to pass through. In this blog, we’ll delve into the world of RxJS filtering operators, exploring their capabilities with clear explanations and practical examples to get you started.

Whether you’re a seasoned developer or new to RxJS, understanding filtering operators is key to harnessing the full potential of reactive programming. These operators help streamline data processing, making your code cleaner and more efficient. Let’s dive into the fascinating world of RxJS filtering operators.

List of Filtering Operators

(Note: “⭐ — commonly used”)

  • audit: Ignores source values for a duration and then emits the most recent value.
  • auditTime: Ignores source values for a fixed duration and then emits the most recent value.
  • debounce: Delays the emission of values until a specified time has passed without another emission.
  • debounceTime: Delays the emission of values by a fixed time.
  • distinct: Emits unique values from the source observable.
  • distinctUntilChanged: Emits values only when the current value is different from the previous value.
  • distinctUntilKeyChanged: Emits values only when the specified key changes.
  • elementAt: Emits the single value at a specified index.
  • filter: Emits values from the source observable that pass a provided condition.
  • first: Emits only the first value (or the first value that meets some condition) from the source observable.
  • ignoreElements: Ignores all items emitted by the source observable and only passes calls of complete or error.
  • last: Emits only the last value (or the last value that meets some condition) from the source observable.
  • sample: Emits the most recent value from the source observable whenever another observable emits.
  • sampleTime: Emits the most recent value from the source observable at specified time intervals.
  • single: Emits only the first value that matches a predicate, and errors if there is more than one match.
  • skip: Suppresses the first n values emitted by the source observable.
  • skipLast: Suppresses the last n values emitted by the source observable.
  • skipUntil: Suppresses the items emitted by the source observable until another observable emits an item.
  • skipWhile: Suppresses the items emitted by the source observable as long as a specified condition is true.
  • take: Emits only the first n values emitted by the source observable.
  • takeLast: Emits only the last n values emitted by the source observable.
  • takeUntil: Emits values from the source observable until another observable emits an item.
  • takeWhile: Emits values from the source observable while a specified condition is true.
  • throttle: Emits a value from the source observable, then ignores subsequent values for a duration determined by another observable.
  • throttleTime: Emits a value from the source observable, then ignores subsequent values for a specified duration.

Now we will review each Filtering Operator one by one and learn through examples.

audit

The audit operator ignores source values for a specified duration and then emits the most recent value after that duration has passed. This operator is like a quality control inspector, ensuring that only the most recent value is emitted within a specified time window.

/* This example emits the most recent value from the source every 2 seconds.*/

import { interval } from 'rxjs';
import { audit } from 'rxjs/operators';

const source = interval(1000); // emit values every 1 second
const example = source.pipe(audit(val => interval(2000))); // only emit values every 2 seconds
example.subscribe(val => console.log(val));

auditTime

The auditTime operator is similar to audit but uses a fixed time to control the data flow.

/* This example emits the most recent value every 2 seconds. */

import { interval } from 'rxjs';
import { auditTime } from 'rxjs/operators';

const source = interval(1000);
const example = source.pipe(auditTime(2000));
example.subscribe(val => console.log(val));

debounce

The debounce operator delays the emission of a value from the source Observable until a particular time has passed without another source emission. This operator is like a calm and patient friend, waiting for a specified time before emitting the latest value.

/* wait 500ms before emitting event while typing in input field. */ 

import { fromEvent } from 'rxjs';
import { debounce } from 'rxjs/operators';

const input = document.getElementById('myInput');
const inputEvents = fromEvent(input, 'input');
const debounced = inputEvents.pipe(debounce(500));

debounced.subscribe(console.log);

debounceTime

The debounceTime operator delays the emissions of the source Observable values by the specified time.

/* This example delays the emission of click events by 1 second. */

import { fromEvent } from 'rxjs';
import { debounceTime } from 'rxjs/operators';

const clicks = fromEvent(document, 'click');
const result = clicks.pipe(debounceTime(1000));
result.subscribe(x => console.log(x));

distinct

The distinct operator emits all items from the source Observable that are distinct by comparison.

/* This example emits only unique values: 1, 2, 3.*/

import { of } from 'rxjs';
import { distinct } from 'rxjs/operators';

const source = of(1, 1, 2, 2, 3, 3);
const example = source.pipe(distinct());
example.subscribe(val => console.log(val));

/* Output
1, 2, 3
*/

distinctUntilChanged

The distinctUntilChanged operator emits all items from the source Observable that are distinct by comparison with the previous item. Similar to distinct, distinctUntilChanged ensures that only unique values are emitted, but only if the previous value is different.

/* This example emits values only when the current value is different from the previous value. */

import { of } from 'rxjs';
import { distinctUntilChanged } from 'rxjs/operators';

const source = of(1, 2, 2, 3, 3, 1);
const example = source.pipe(distinctUntilChanged());
example.subscribe(val => console.log(val));

/* Output
1, 2, 3, 1
*/

distinctUntilKeyChanged

The distinctUntilKeyChanged operator ensures that only unique values are emitted based on a specified key.

/* This example emits objects only when the specified key (name) changes. */

import { of } from 'rxjs';
import { distinctUntilKeyChanged } from 'rxjs/operators';

const source = of(
{ name: 'Brian' },
{ name: 'Joe' },
{ name: 'Joe' },
{ name: 'Sue' }
);
const example = source.pipe(distinctUntilKeyChanged('name'));
example.subscribe(val => console.log(val));

/* Output
{name: "Brian"}
{name: "Joe"}
{name: "Sue"}
*/

elementAt

The elementAt operator emits a single value at the specified index.

/* This example emits the third value (index 2): 3. */

import { from } from 'rxjs';
import { elementAt } from 'rxjs/operators';

const source = from([1, 2, 3, 4, 5]);
const example = source.pipe(elementAt(2));
example.subscribe(val => console.log(val));

filter

The filter operator emits values from the source Observable that pass a provided condition.

/* This example emits only even numbers: 2, 4. */

import { from } from 'rxjs';
import { filter } from 'rxjs/operators';

const source = from([1, 2, 3, 4, 5]);
const example = source.pipe(filter(num => num % 2 === 0));
example.subscribe(val => console.log(val));

first

The first operator emits only the first value (or the first value that meets some condition) from the source Observable, then completes.

/* This example emits the first value: 1. */

import { from } from 'rxjs';
import { first } from 'rxjs/operators';

const source = from([1, 2, 3, 4, 5]);
const example = source.pipe(first());
example.subscribe(val => console.log(val));

ignoreElements

The ignoreElements operator ignores all items emitted by the source Observable and only passes calls of complete or error.

/* This example emits nothing and just completes. */

import { from } from 'rxjs';
import { ignoreElements } from 'rxjs/operators';

const source = from([1, 2, 3, 4, 5]);
const example = source.pipe(ignoreElements());
example.subscribe({
next: val => console.log(val),
error: err => console.log(err),
complete: () => console.log('Complete...All values ignored!')
});

last

The last operator emits only the last value (or the last value that meets some condition) from the source Observable.

/* This example emits the last value: 5. */

import { from } from 'rxjs';
import { last } from 'rxjs/operators';

const source = from([1, 2, 3, 4, 5]);
const example = source.pipe(last());
example.subscribe(val => console.log(val));

sample

The sample operator emits the most recent value from the source Observable whenever another Observable (the notifier) emits.

/* This example emits the most recent value from the source every 2 seconds. */

import { interval } from 'rxjs';
import { sample } from 'rxjs/operators';

const source = interval(1000);
const example = source.pipe(sample(interval(2000)));
example.subscribe(val => console.log(val));

sampleTime

The sampleTime operator emits the most recent value from the source Observable at specified time intervals.

/* This example emits the most recent value every 2 seconds. */

import { interval } from 'rxjs';
import { sampleTime } from 'rxjs/operators';

const source = interval(1000);
const example = source.pipe(sampleTime(2000));
example.subscribe(val => console.log(val));

single

The single operator emits only the first value (or the first value that meets some condition) from the source Observable that matches a predicate, and errors if there is more than one match.

/* This example filters an array of objects and emits only the object with an id of 3 */

import { from } from 'rxjs';
import { single } from 'rxjs/operators';

const source = from([
{ id: 1, name: 'John' },
{ id: 2, name: 'Jane' },
{ id: 3, name: 'Bob' },
{ id: 4, name: 'Alice' },
]);

const example = source.pipe(single(val => val.id === 3));
example.subscribe(val => console.log(val));

/* Output
{id: 3, name: "Bob"}
*/

skip

The skip operator suppresses the first n values emitted by the source Observable.

/* This example skips the first two values and emits: 3, 4, 5. */

import { from } from 'rxjs';
import { skip } from 'rxjs/operators';

const source = from([1, 2, 3, 4, 5]);
const example = source.pipe(skip(2));
example.subscribe(val => console.log(val));

skipLast

The skipLast operator suppresses the last n values emitted by the source Observable.

/* This example skips the last two values and emits: 1, 2, 3. */

import { from } from 'rxjs';
import { skipLast } from 'rxjs/operators';

const source = from([1, 2, 3, 4, 5]);
const example = source.pipe(skipLast(2));
example.subscribe(val => console.log(val));

skipUntil

The skipUntil operator suppresses the items emitted by the source Observable until another Observable (the notifier) emits an item.

/* This example skips values emitted by the source until 5 seconds have passed. */

import { interval, timer } from 'rxjs';
import { skipUntil } from 'rxjs/operators';

const source = interval(1000);
const example = source.pipe(skipUntil(timer(5000)));
example.subscribe(val => console.log(val));

skipWhile

The skipWhile operator suppresses the items emitted by the source Observable as long as a specified condition is true.

/* This example skips values while they are less than 3 and emits: 3, 4, 5. */

import { from } from 'rxjs';
import { skipWhile } from 'rxjs/operators';

const source = from([1, 2, 3, 4, 5]);
const example = source.pipe(skipWhile(val => val < 3));
example.subscribe(val => console.log(val));

take

The take operator emits only the first n values emitted by the source Observable.

/* This example emits the first three values: 1, 2, 3.*/

import { from } from 'rxjs';
import { take } from 'rxjs/operators';

const source = from([1, 2, 3, 4, 5]);
const example = source.pipe(take(3));
example.subscribe(val => console.log(val));

takeLast

The takeLast operator emits only the last n values emitted by the source Observable.

/* This example emits the last three values: 3, 4, 5.*/

import { from } from 'rxjs';
import { takeLast } from 'rxjs/operators';

const source = from([1, 2, 3, 4, 5]);
const example = source.pipe(takeLast(3));
example.subscribe(val => console.log(val));

takeUntil

The takeUntil operator emits values from the source Observable until another Observable (the notifier) emits an item.

/* This example emits values from the source until 5 seconds have passed.*/

import { interval, timer } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

const source = interval(1000);
const example = source.pipe(takeUntil(timer(5000)));
example.subscribe(val => console.log(val));

takeWhile

The takeWhile operator emits values from the source Observable while a specified condition is true.

/* This example emits values while they are less than 4 and emits: 1, 2, 3.*/

import { from } from 'rxjs';
import { takeWhile } from 'rxjs/operators';

const source = from([1, 2, 3, 4, 5]);
const example = source.pipe(takeWhile(val => val < 4));
example.subscribe(val => console.log(val));

throttle

The throttle operator emits a value from the source Observable, then ignores subsequent source values for a duration determined by another Observable, and then repeats this process.

/* This example emits a value and then ignores new values for 2 seconds. */



import { interval } from 'rxjs';
import { throttle } from 'rxjs/operators';

const source = interval(1000);
const example = source.pipe(throttle(val => interval(2000)));
example.subscribe(val => console.log(val));

throttleTime

The throttleTime operator emits a value from the source Observable, then ignores subsequent source values for the specified duration, and then repeats this process.

/* This example emits a value and then ignores new values for 2 seconds.*/

import { interval } from 'rxjs';
import { throttleTime } from 'rxjs/operators';

const source = interval(1000);
const example = source.pipe(throttleTime(2000));
example.subscribe(val => console.log(val));

Conclusion:

In this article, we explored the world of RxJS filtering operators, learning how to use them to refine and filter data streams. By mastering these operators, you can tame the data storm and extract the most relevant information from your data streams.

Happy coding!

--

--