Map, switchMap, mergeMap, flatMap, concatMap, exhaustMap in RxJS - what is the difference?
Map, switchMap, mergeMap, flatMap, concatMap, exhaustMap in RxJS - what is the difference?

In this post you will learn once and forever what is the difference between map methods inside RxJS. It is map, switchMap, concatMap, flatMap, mergeMap and exhaustMap.

The main problem is that it is really difficult to understand the difference between all this methods. You open documentation, you might understand one method and then you don't understand in what case what method you should use.

Then you jump to Stack Overflow to solve your specific problem and you see that people use different methods for exactly the same solution. Then you are wondering if it makes any difference at all to use some of these methods.

This is why here I prepared for you a simple example to understand all these methods.

Map

The first method here is map. Actually map is completely different from other methods. When we use map we simply want to change the source of our stream without usage of subscribe.

foo$ = from([1,2,3,4,5]).pipe(map((item) => item * 10))

Here we used from to create a changed stream. In order to modify every single element we transform them with map. This allows us to multiply them by 10 in this case.

Map

As you can see we are getting multiplied values.

We are using map when we transform values of our stream without using subscribe.

In order to understand other methods I have an additional function.

const example = (operator: any) => () => {
  from([0, 1, 2, 3, 4])
    .pipe(operator((x: any) => of(x).pipe(delay(500))))
    .subscribe(
      console.log,
      () => {},
      () => console.log(`${operator.name} completed`)
    );
};

//example(mergeMap)();

Here we will throw different operators inside example function and check how they work. Inside we create a stream from 0 to 4 and create a new stream with 500 ms delay for every value.

mergeMap / flatMap

First let's talk about mergeMap and flatMap. You must remember that flatMap is just an alias to mergeMap and it is deprecated inside RxJS.

Merge map

As you can see we directly get all these values inside console with a single 500ms delay. mergeMap creates directly observable from our source but it doesn't cancel any existing observables.

Every single time when we create new observable from our value and delay it we jump directly to the next value without waiting for first observable to complete.

So with mergeMap all previous observables are ignored and we simply create new one.

If we try to change mergeMap to flatMap you will see the same result as this is just an alias.

concatMap

The next one in our list of concatMap.

Concat map

The difference here is that we can see the delay 500ms between every value. Which means with concatMap we are waiting for previous observable to complete before we create a new observable.

concatMap waits for previous observable to be completed.

The usage of concatMap is when you need to create an observable based on the previous observable. mergeMap on the other hand won't wait for the result.

switchMap

Now let's try switchMap.

Switchmap

As you can see we get just 4.

switchMap cancels every previous observable

When we create observable for 0 and we delay it with 500ms we directly create an observable for 1 which cancels our observable for 0. This is why at the end we just get a single observable of 4.

exhaustMap

The last method that we want to check is exhaustMap.

ExhaustMap

Here we get just 0 because all next observables are ignored until the first one won't be completed. As our first observable is being delayed by 500ms we ignore all other observables. This is why we see just 0.

Real problem

Real problem

Here is an example of real use case when we want to make 2 API requests one by one. Because second request needs result from the first one we want to wait for the completion. This is why in the code you can see that we used concatMap. This is the most correct way and in browser we can see detail information as a result.

But we can easily change concatMap to switchMap at it will bring exactly the same result. Yes switchMap cancels the previous observable but with a single value as an API response it doesn't matter so in this case both these methods are working the same.

But this is exactly what leads to the confusion if you don't know the differences between these methods.

And actually if you want to learn Angular with NgRx from empty folder to a fully functional production application make sure to check my Angular and NgRx - Building Real Project From Scratch course.