7
votes

Effect:

@Effect()
  loadDocsEffect$ = this.actions$.pipe(
    ofType(myActionTypes.LoadDocs),
    mergeMap(action => this.myService.getDocs()),
    map(data => new LoadDocsSuccess(data)),
    catchError(error => Observable.of(new LoadDocsFailure(error)))
  );

It works when I have data returned, but when the server responds with an error - 404 for example, the observable is complete and doesn't trigger the effect the second time I dispatch an action. I looked for a way to handle the error properly and to continue the observable stream so I could subscribe to it in my component and act accordingly.

The solution in @ngrx Effect does not run the second time did not work for me, or I couldn't make it work.

2

2 Answers

13
votes

You need to catchError on request instead of the actions$. To do this, you will need to modify your code as following:

mergeMap(action => 
  this.myService.getDocs().pipe(
    map(data => new LoadDocsSuccess(data)),
    catchError(error => Observable.of(new LoadDocsFailure(error)))
  )
)
3
votes

I guarantee you that this is the right way to do it. How do I know? There is a long talk about this exact issue on the ngrx Udemy course and this is the solution they provide. Note that is is essential to use catchError else an HTTP error response (any non 2xx response) will disable this effect.

@Effect()
  loadDocsEffect$ = this.actions$.pipe(
    ofType(myActionTypes.LoadDocs),
    mergeMap((action) => {
      // essential to catchError else an HTTP error response will disable this effect
      return this.myService.getDocs().pipe(
        map(data => new LoadDocsSuccess(data)),
        catchError((err) => {
          return of(null)
        })
      )
    }),
    tap(res => console.log(res)) // you won't want this line but useful for debugging
  );

In this example, if the HTTP request succeeds the result of new LoadDocsSuccess(data) will be logged inside tap. If the HTTP request fails, null will be logged inside tap. Of course, you may want to provide some different catchError logic but you get the idea.