RxJS Mastery – #33 mergeMap

RxJS mergeMap lesson title

The RxJS mergeMap operator is another one of those flattening operators (e.g. like concatMap). It maps values to an inner Observable and finally merges the values returned by the inner Observable to the output.

Map to inner Observables and merge those into the output

A basic example can be constructed by merging numbers to an inner Observable and applying a mapping. In this case the output would just be the mapped number 2, 4, 6, and 8:

const result$ = of(1,2,3,4).pipe(
    mergeMap(v => of(v * 2)),
);

result$.subscribe((v) => console.info(v));

This example is not very meaningful though as it constructs an inner Observable unnecessarily with of(). Nevertheless we see that mergeMap can flatten an inner Observable, compared to map that is just used on plain values.

Having multiple inner Observables active and subscribed to

Sometimes you hear that mergeMap should be used when you want parellel execution of inner Observables. This makes sense and so is the operator used when you don’t want to cancel inner Observables (compared to switchMap) and don’t want to have order (compared to concatMap). Imagine the following NgRx construct where we have an action that causes http calls to be executed:

@Effect()
createObject$ = this.actions$.pipe(
  ofType(ObjectActionTypes.Create),
  map((action: CreateObject) => action.payload),
  mergeMap((object: ObjectData) =>
    this.objectHttpService
      .create(object)
      .pipe(
        map(object => new ObjectCreated({ object }))
      )
   )
);

The RxJS mergeMap operator makes sure that multiple CreateObject effects can run in parallel. When one request of objectHttpService is running and a second action emits, it will be considered and also executed.

The RxJS flatMap operator is mergeMap

Often we also see the flatMap operator. As the name suggests this operator flattens Observables. Hence, it’s doing the same as mergeMap. So, where is the difference? There is none because this is the “implementation” of flatMap:

export const flatMap = mergeMap;

Exercise for the RxJS mergeMap operator 💪

Use mergeMap with the concurrent parameter set to 1. To which other operator is the behaviour comparable? The following example could help where the inner Observable completes faster with increasing index:

const result$ = of(1,2,3,4).pipe(
    mergeMap((v: number, index: number) => interval(1000/(index+1))
        .pipe(
            take(1),
            map(i => `emitted value for ${v} (waiting time ${1000 / (index+1)})`)
        ),
    1),
);

result$.subscribe({
    next: console.log,
    complete: () => done(),
});

As always the code examples and exercise solution can be found on GitHub.