RXJS has a broad set of observable operators such as flatMap, mergeMap, concatMap, that can be used to do nifty things. One particular operator that I will cover in this post is called switchMap. A switchMap is not a switch statement in the traditional sense where you define a list of conditions along with logic blocks and invoke a logic block that satisfies a condition, rather it is a handy control flow operator that can be used to prevent race condition problems on the frontend.
What are Race Condition Problems?
Race condition is an undesired situation that occurs when two or more operations need to happen in sequence but don’t. For instance, a common race condition problem is when two ajax requests are made from the frontend to the backend simultaneously. The first request may experience a delay and return data after the second request, consequently overwriting the data that has been returned by the second request.
SwitchMap receives emitted values from an outer observable known as the data source. A data source can be an Angular httpClient, a user event, or you can create your own. For demonstration purposes I created a data source observable, and I’m using its observer to emit values to the switchMap operator.
The switchMap operator has the following signature :
switchMap(project: function: Observable, resultSelector: function(outerValue, innerValue, outerIndex, innerIndex): any): Observable
It subscribes to the project observable internally and only keeps one inner subscription active at a time. Each time there is an emission by the outer observable, it cancels its subscription and creates a new subscription to the new project observable. This ensures that only the latest value gets emitted to your subscriber.
Here is an example of a switchMap in action. Notice in the following code block the first call has a delay of 10 and the second call has a delay of 5.
And here is a plunker if you want to see the code in action.
Plunker is an online community for creating, collaborating on and sharing your web development ideas.
If the switchMap operator wasn’t used, we would have that race condition problem described earlier. The second request would finish before the first and load its data to the frontend. Then the first request would complete, and load its data to the frontend replacing the data that has already been loaded by the most recent request. As a result of this problem, the application would be using stale data.
What We Learned?
SwitchMap operators are useful in situations where the most current data matters. For example, when there are multiple requests sent to the backend at the same time, we end up having a race condition problem. The backend may not respond in the same order the requests were made. SwitchMaps unique ability to cancel its subscription to its internal observable and create a new one for the most recent event ensures us our subscriber will always receive the latest data.