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));
);
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));
);
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));
);
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
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
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
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
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)