1

I am new to rxjs and working with redux-observable and have a question about where to use the catchError function from rxjs.

I have the following code working how I want it to:

function countEpic(action$: Observable<AnyAction>): Observable<AnyAction> {
  return action$
    .pipe(
      map(logEpic)
      ,ofType(RESET_REQUEST)
      ,flatMap(action =>
        resetCountService(action)
          .pipe(
            map(logEpic)
            ,map(newCount => ({ type: RESET_SUCCESS, payload: newCount }))
            ,catchError((error: any, caught: Observable<AnyAction>) => of({ type: RESET_FAILURE }))
          )
      )
    );
}

function resetCountService(action: AnyAction): Observable<number> {;
  return of(7)
    .pipe(
      map(newCount => { throw "broke" })
    );
}

NOTE: the resetCountService is just a mock service in place of an API service that would return an Observable in the future

before I had

function countEpic(action$: Observable<AnyAction>): Observable<AnyAction> {
  return action$
    .pipe(
      map(logEpic)
      ,ofType(RESET_REQUEST)
      ,flatMap(resetCountService)
      ,map(newCount => ({ type: RESET_SUCCESS, payload: newCount }))
      ,catchError((error: any, caught: Observable<AnyAction>) => of({ type: RESET_FAILURE })))
      )
    );
}

In my code (the before I had code) the catchError seemed to "stop" the Observable pipe from continuing and I'm not sure why. My question is why do I need to catchError on the "inner" Observable rather than catching it on the epic Observable? All answers and links are appreciated!

jo_wil
  • 369
  • 3
  • 11
  • This answer is for NgRx, but it applies to redux-observable, too: https://stackoverflow.com/a/41685689/6680611 – cartant Jul 11 '18 at 23:14
  • And see the [`rxjs-no-unsafe-catch`](https://github.com/cartant/rxjs-tslint-rules#rxjs-no-unsafe-catch) rule in `rxjs-tslint-rules`. – cartant Jul 11 '18 at 23:15
  • @cartant thank you for the link to the question as well as the linting rule. After a brief look at these I found "When the observable errors and catch returns a empty obervable, the composed observable completes and its subscribers are unsubscribed - that's part of the Observable Contract" in that stackoverflow post. Since my catch error does not return an empty observable why is it still being unsubscribed? I understand now that the way I ended up with is the correct way to do things, I am now trying to fully understand the problems with the other way. Thanks again! – jo_wil Jul 12 '18 at 01:31
  • It unsubscribes because the observable stream **continues with the observable returned** from `catchError`. You are returning an observable created using `of` - which **completes**, effecting automated unsubscription. – cartant Jul 12 '18 at 01:35
  • 1
    You might also want to read Paul's article (it's about NgRx, but is also relevant to redux-observable): https://medium.com/city-pantry/handling-errors-in-ngrx-effects-a95d918490d9 – cartant Jul 12 '18 at 01:37
  • @cartant awesome answers thanks so much, I think I get this now! Also that article was great. – jo_wil Jul 12 '18 at 16:24
  • Yes catchError is kind of like switchMap in that it returns a new observable. You can think of it as switchOnError – Simon_Weaver Jan 20 '19 at 10:12

0 Answers0