Demo: switchMap
switchMap => map + switchAll switches to the latest the mapped observable.
The switchMap maps the source items to desired tasks for execution and, immediately switches to the latest task, cancelling any unfinished task for an older item.
This feature is useful when only the latest requests are considered important and the older one represent the obsolate request, needing to be discarded.
const source = timer(500,2500).pipe(take(3));
//1. Each input from source maps to this counting task
const countTill3Task = timer(0,1700).pipe(take(4);
//2. switchMap keeps switching to the latest countTill3Task,
// cancelling any unfinished older task.
const mapAndSwitchToLatest = switchMap(v => countTill3Task );
const output = source.pipe(mapAndSwitchToLatest)
.subscribe(v=>console.log(v));
The switchMap is a combination of the map and the switch all operator.
- To start with the map part, maps our input to an observable that specifies our intended task.
- Then, it submits them for execution by switchAll operator.
- The switchAll operator is designed to always switch to execute only the latest task, cancelling any unfinished older task.
Coming to our demo on switchMap:
- The first part, maps each of our input to a count till 3 task.
- The 2nd part, always switches to the newly mapped count till 3 task, cancelling any already in-progress counting task. As a result, in the output of the demo, we can see:
- The switchMap started the countTill3Task for 1 as it arrived, cancelling the on-going count task for 0.
- Again, started the countTill3Task for 2 as it arrived, cancelling the on-going count task for 1. This is one usage of switchMap where we are using it for re-starting a counter task. We will look at more of it's usages later on in the post.
The switchMap is useful where we want to run only the latest request and cancel the older ones, because they have become obsolate, so no more needed.
As seen in the demo, on every new input switchMap starts the newly mapped countTill3Task and keeps cancelling the earlier incomplete task.
The behaviour is just complementary to that of exhaustMap
Usages
1. Switching between multiple states
- For use-cases like start-pause-restart
Let's say we are implementing a stopwatch with options to - start, pause and restart.
Now, each state needs a different observable(or task) to run, one replacing the other. The demo below shows how to achieve this using a switchMap.
What is happening in the demo?
On the switchMap part, the operator is switching between 2 observables:
- When the status is 'start', it immediately starts the ticking task.
- For the other two status, it's switching to
EMPTY
observables representing the idle tasks.
2. Switch to the latest request and abort any on-going one
Let's say the user is searching for some product in a online shopping website. And, before the result appears, the user submits a different product search request.
It's quite a valid scenario where the user expects the response for his latest request and no longer wants the response for his earlier request. The switchMap can do both of the above task for us with ease.