Search code examples
angulartypescriptrxjsngrxmergemap

NgRx effect mergeMap approach


I have two implementations of the same effect, and both work. I'm having a hard time understanding the differences between the two and which is more "correct".

Please find them below:

Option 1. IDE cannot figure out the type for instance in the last map.

    pollingStarted$ = createEffect(() =>
        this.actions$.pipe(
            ofType(pollingStarted),
            mergeMap(action => action.instances),
            map(instance => performRequest({ instance }))
        )
    );

Option 2. All types work out and make sense. This is more correct to me but I want to figure out and understand the differences.

   pollingStarted$ = createEffect(() =>
        this.actions$.pipe(
            ofType(pollingStarted),
            mergeMap(({ instances }) =>
                instances.map(instance => performRequest({ instance }))
            )
        )
    );

Solution

  • It seems that the first approach should not work:

    pollingStarted$ = createEffect(() =>
        this.actions$.pipe(
            ofType(pollingStarted),
            mergeMap(action => action.instances),
            map(instance => performRequest({ instance }))
        )
    );
    

    mergeMap in this case flats your array, and map returns an Observablve for each emitted value. At the end you get an Observable of Observables (Observable<Observable<your type>>). You need to use one of Higher Order Observables instead of map to make it working.

    Second option is the right one:

    pollingStarted$ = createEffect(() =>
        this.actions$.pipe(
            ofType(pollingStarted),
            mergeMap(({ instances }) =>
               instances.map(instance => performRequest({ instance }))
            )
         )
     );
    

    mergeMap in this case merges an array of observables produced by instances.map into a single observable. The benefit of using this approach is that you have control over observables, you can apply catchError to each performRequest or apply it on a higher level after mergeMap to have a single error handling for all performRequest calls.