RxJS Operators in Angular – and everywhere else!

As we said in the beginning, RxJS is agnostic to frameworks and libraries. However, you will see a preeminent use of RxJS operators in Angular.

Operators are functions. 

In RxJS, items go through operators that can transform, filter, and process those items. In other words, items are piped through operators.

There are two kinds of operators:

  1. Creation Operators. Call them as standalone functions to create a new Observable.
  2. Pipeable Operators. They can be piped to Observables e.g.  myObservable.pipe(operator()).

1. Creation Operators

Here is an example using the <a href="https://rxjs.dev/api/index/function/of" target="_blank" rel="noreferrer noopener">of</a> creation operator to create a new observable. The of operator converts the items to an observable sequence, emits all the items, and complete.

of(1, 2, 3)
  .subscribe(
    next => console.log('next:', next),
    err => console.log('error:', err),
    () => console.log('the end'),
);

// Outputs
// next: 1
// next: 2
// next: 3
// the end

Notice that, for our purpose, this can be simplified as follow:

of(1, 2, 3)
  .subscribe(x => console.log(x));

// Outputs
// 1
// 2
// 3

If you want to see a practical example using of , have a look at Hands-on-3: RxJS Of, RxJS From.

2. Pipeable Operators

Here is an example using the map operator. Like Array.prototype.map(), the rxjs map operator transform each item according to a transformation function.

First, we create an observable sequence using the creation operator of. In this case, of(1,2,3) is the source observable.

Second, we pipe the map operator to the source observable. To pipe an operator, we need to call .pipe( ... ) on the observable. Whatever the observable emits goes through the pipe. Inside the pipe there can be one or multiple operators that will process the emitted item.

Third, we subscribe. When we subscribe, the source observable starts to emit items. Each item is piped through the map operator in sequence. The map operator processes each item, one by one.

Finally, the observer’s next method process the values. In the example below, the observer’s next method is a function that logs the value. Side note: instead of x => console.log(x) we can just use console.log.

of(1, 2, 3)
  .pipe(map((x) => x * x))
  .subscribe(console.log);

// Logs:
// 1
// 4
// 9

Remember that pipeable operators “do not change the existing Observable instance. Instead, they return a new Observable, whose subscription logic is based on the first Observable. […] It is a pure operation: the previous Observable stays unmodified”, RxJS.

Piping multiple operators

RxJS allows to pipe multiple operators as follow:

of(1, 2, 3)
  .pipe(
    operator1(),
    operator2(),
    operator3()
  )
  .subscribe(console.log);

When we subscribe to of(1, 2, 3), each item emitted by the observable goes through each operator sequentially.

Every operator takes an observable in input, processes the observable, and returns an output observable.

Finally, the output observable feeds into the next operator.

Find a list of RxJS operators.

rxjs operator list
Some of the RxJS Operators available in rxjs

Rxjs.dev proposes an operator decision tree which might simplify your choice of operator.

Operator decision tree on rxjs.dev
Operator decision tree on rxjs.dev

 RxJS operators | map operator