---
status: "published"
title: "The Simple Difference Between RxJS switchMap and mergeMap"
date: "2018-03-19"
description: "Trying to figure out whether to use switchMap or mergeMap for a simple HTTP request? I only understood the difference once I tried it out for myself."
image: "https://github.com/user-attachments/assets/ef8b2d85-d867-4b3d-9d00-16d9d6da1f02"
imageAlt: "RxJS switchMap and mergeMap data flow"
author: "Vlad Sabev"
authorUrl: "https://github.com/vdsabev"
authorAvatar: "https://github.com/vdsabev.png"
tags: ["angular","rxjs","software development"]
navigationIndex: 0
---

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`:

```typescript
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:

<img width="859" height="239" alt="Canceled network calls with switch map" src="https://github.com/user-attachments/assets/60be1ef9-ba4b-43bf-aee4-b63239eb388e" />

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:

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

The results this time are:

<img width="859" height="238" alt="Successful network calls with mergeMap" src="https://github.com/user-attachments/assets/ecd96309-3563-4c19-9a7f-cb3d22fec196" />

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 👇

