DEV Community

Cover image for RxJS Mapping: Behind the scenes
Strahinja Obradovic
Strahinja Obradovic

Posted on • Updated on

RxJS Mapping: Behind the scenes

Photo by TopSphere Media on Unsplash

A hands-on look at how higher-order operators work behind the scenes.

SwitchMap, MergeMap, ConcatMap, or ExhaustMap? Choosing the right one can be confusing, but we'll unravel their differences by taking a peek behind the scenes.

To make things even more exciting, I'll provide a simulator at the end so you can interact with the maps and see their differences come to life.

Map suffix

Why do we need higher-order operators?

Higher-order operators are necessary to handle higher-order observables, which are observables of observables. In the context of higher-order observables, we have inner and outer (source) observables. Whenever a new page is emitted (outer), we make an HTTP request (inner) to retrieve the corresponding data.

const data = pageObservable$.pipe(
 higherOrderOperatorHere(page => http.get(page));
);
Enter fullscreen mode Exit fullscreen mode

What does it mean to "handle" higher-order observables?

When we use an ordinary RxJS map operator, each page number is mapped to an Observable, resulting in observing observables instead of values.

const data: Observable<Observable<Data>> = pageObservable$.pipe(
 map(page => http.get(page));
);
Enter fullscreen mode Exit fullscreen mode

Higher-order operators handle exactly that, plus some additional functionality depending on the prefix (switch, merge, exhaust, and concat).

const data: Observable<Data> = pageObservable$.pipe(
 higherOrderOperatorHere(page => http.get(page));
);
Enter fullscreen mode Exit fullscreen mode

Switch, Exhaust, Merge, or Concat

Switch, exhaust, merge, and concat are policies for managing concurrency between inner observables. This concurrency arises from the asynchronous processing of each source.

Let's explore each of these operators and their functions. We will illustrate this entire process using a finite-state machine.

SwitchMap

SwitchMap
States: [Start, Active, Canceled, Completed]
Final states: [Canceled, Completed]
Transitions:

From Start to Active
Condition: new source emitted.

From Active to Completed
Condition: inner observable completed.

From Active to Canceled
Condition: new source emitted.

ExhaustMap

exhaustMap
States: [Start, Active, Canceled, Completed]
Final states: [Canceled, Completed]
Transitions:

From Start to Active
Condition: new source emitted & no other active inner observable.

From Start to Canceled
Condition: new source emitted & other active inner observable.

From Active to Completed
Condition: inner observable completed.

MergeMap

mergeMap
States: [Start, Active, Completed]
Final state: Completed

Transitions:

From Start to Active
Condition: new source emitted.

From Active to Completed
Condition: inner observable completed.

ConcatMap

concatMap
States: [Start, Queued, Active, Completed]
Final state: Completed

Transitions:

From Start to Active
Condition: new source emitted & no other active inner observable.

From Start to Queued
Condition: new soure emitted & other active inner observable.

From Active to Completed
Condition: inner observable completed.

From Queued to Active
Condition: head of the queue & no other active inner observable.

Hands-On Demo

When I said "hands-on look" I meant it literally.
Set up a scenario and see how the maps behave!

Thanks for reading!

P.S. If you are interested in practical examples of using these operators, take a look at this article.

Top comments (0)