‘switchMap‘, ‘mergeMap‘, and ‘concatMap‘ are all higher-order mapping operators in RxJS, used to deal with observables that emit other observables. They handle the combination and emissions of values from inner observables differently. Let’s discuss each of them in detail with examples:
1. ‘switchMap‘
‘switchMap‘ maps each value from the source observable to an inner observable, and then it’ll only emit values from the most recently mapped inner observable. If the source observable emits new values before the inner observable completes, it will switch and start emitting values from that new inner observable, abandoning the previous ongoing inner observable.
Use Case: A search bar that fetches search results as the user types. You only want to show the results for the most recent search term.
// RxJS v6+ import style
import { fromEvent } from 'rxjs';
import { switchMap } from 'rxjs/operators';
const searchBox = document.querySelector('.search-box');
const searchTerm$ = fromEvent(searchBox, 'input');
const searchResults$ = searchTerm$.pipe(
switchMap((val) => getSearchResults$(val))
);
searchResults$.subscribe((results) => {
displaySearchResults(results);
});
2. ‘mergeMap‘
‘mergeMap‘ maps each value from the source observable to an inner observable and emits values from all active inner observables simultaneously. It has an optional argument ‘concurrent‘ that sets the maximum number of concurrent inner subscriptions (default is Infinity).
Use Case: Multiple asynchronous requests where the order of the response does not matter.
// RxJS v6+ import style
import { of } from 'rxjs';
import { mergeMap } from 'rxjs/operators';
const ids = [1, 2, 3, 4];
const source$ = of(...ids);
const response$ = source$.pipe(
mergeMap((id) => getData$(id))
);
response$.subscribe((responseData) => {
processData(responseData);
});
3. ‘concatMap‘
‘concatMap‘ is similar to ‘mergeMap‘, but it will concatenate the inner observables instead of merging them. It maintains the order of the source observable emissions and ensures that inner observables complete before starting a new inner observable.
Use Case: A series of tasks that need to be executed in order, where each task’s result depends on the previous task result.
// RxJS v6+ import style
import { of } from 'rxjs';
import { concatMap } from 'rxjs/operators';
const tasks = ['Task 1', 'Task 2', 'Task 3'];
const source$ = of(...tasks);
const result$ = source$.pipe(
concatMap((task) => executeTask$(task))
);
result$.subscribe((taskResult) => {
updateStatus(taskResult);
});
In conclusion, ‘switchMap‘ is used when you need to switch to the latest inner observable and ignore previous ones, ‘mergeMap‘ is used when you want to emit values from multiple observables concurrently and order doesn’t matter, and ‘concatMap‘ is used when you need to maintain the order of inner observables and wait for each to complete before starting the next.