2

In the code snippet below, I want to emit a GetData action if the update operation was successful or a BackendError action if unsuccessful.

@Effect()
updateData$ = this.actions$.pipe(
  ofType(MyActionType.UPDATE_DATA),
  map((action: UpdateData) => action.payload),
  combineLatest(this.authService.getUser(), (myData, user) => this.dataService.updateData(myData, user)),
  map(() => new GetData()),
  catchError((err) => { of(new BackendError(err)))
);

The above code does not seem to be working. Even though the update operation fails due to permission error, the BackendError action is not emitted.

Any help is appreciated.

Peter
  • 1,720
  • 3
  • 18
  • 30

1 Answers1

1

Your current implementation will swallow errors on the updateData operation, because the action$ (the outer observable) gets mapped to a new GetData() action, regardless of the result of the updateData operation (success or failure).

In the implementation below, the catchError operator will runif the updateData operation (dataUpdate$ -- the inner observable) throws an error..

@Effect()
updateData$ = this.actions$.pipe(
  ofType(MyActionType.UPDATE_DATA),
  mergeMap((action: UpdateData) => {
    const user$ = this.authService.getUser();
    const dataUpdate$ = user$.pipe(
      mergeMap(user => this.dataService.updateData(action.payload, user));
    );
    return dataUpdate$.pipe(
      map(() => new GetData()),
      catchError(err => of(new BackendError(err)))
    );
  })
);

Additional Resources

  1. Here's some more information on the difference between mergeMap and map.
  2. Official docs for mergeMap.
  3. Example of @Effect using this approach in the @ngrx/effects README.
vince
  • 7,808
  • 3
  • 34
  • 41
  • Thanks for your answer, Vince. Your snippet is missing a value for user which is required by `dataService.updateData()`. I have modified it as `dataUpdate$=this.authService.getUser().map(user => this.dataService.updateData(action.payload, user))`, but BackendError action is still not emitted. I have tried to enclose call to `updateData()` in `Observable.fromPromise()` as the `updateData()` method returns a promise, but that did not work either. – Peter Feb 23 '18 at 16:50
  • 1
    No problem! I edited my answer to reflect what you're trying to do. I think you just need another `mergeMap` instead of `map`. See my updated answer and let me know if that works for you. – vince Feb 23 '18 at 17:16