The Simple Difference Between RxJS switchMap and mergeMap

…when dealing with HTTP requests

Vlad Sabev
2 min readMar 19, 2018

Have you been reading about RxJS for the past hour or so, trying to figure out whether you should be using switchMap or mergeMap to handle a simple HTTP request?

That’s exactly what happened to me today, and none of the articles explained the difference in a way that I could understand — there were long paragraphs describing all the details, with many examples using intervals, marble diagrams, and creative analogies.

After all that reading, I only started understanding when I tried it out for myself.

Use case

Let’s get right to it — I wanted to write an @ngrx/effect to send an HTTP request to a metrics service whenever an action was dispatched to the store.

switchMap

Here’s what I came up with initially using switchMap:

import { Injectable } from '@angular/core';
import { of } from 'rxjs/observable/of';
import { catchError } from 'rxjs/operators/catchError';
import { switchMap } from 'rxjs/operators/switchMap';
@Injectable()
export class MetricsEffects {
@Effect({ dispatch: false })
public readonly logToMetrics$ = this.actions$.pipe(
switchMap((action) => this.metricsService.log(action).pipe(
catchError(of)
))
);

constructor(
private actions$: Actions,
private metricsService: MetricsService,
) {
}
}

However, after making 8 requests in quick succession, here’s what the results looked like:

You’ll notice some of those requests got cancelled before they finished. Much like takeLatest in Redux-Saga, switchMap in RxJS only cares about the latest value that the observable emitted, in this case cancelling any previous HTTP requests that were still in progress.

But that wasn’t exactly what I needed.

mergeMap

So let’s try running another 8 requests using mergeMap instead:

  ...
public readonly logToMetrics$ = this.actions$.pipe(
mergeMap((action) => this.metricsService.log(action).pipe(
catchError(of)
))
);
...

The results this time are:

Much like takeEvery in Redux-Saga, mergeMap in RxJS passes all requests through, even when a new request was made before a previous one had finished — exactly what I needed!

Conclusion

So here’s the simple difference — switchMap cancels previous HTTP requests that are still in progress, while mergeMap lets all of them finish.

In my case, I needed all requests to go through, as this is a metrics service that’s supposed to log all actions that the user performs on the web page, so I used mergeMap.

A good use case for switchMap would be an autocomplete input, where we should discard all but the latest results from the user’s input.

Did this help with understanding when to use which? Let me know in the comments 👇

--

--