rxjs error handling with catchError and retry

Viewed 1725

I am trying to catch the errors in rxjs using the catchError operator und want to retry 3 time only if I get an errno=215

return this.httpService.post(url, data).pipe(
  tap(() => {
    console.log(`some debugging info`);
  }),

  map((response) => responseAdaptor(response)),
  retryWhen((error) => {
    return error.pipe(
      scan((acc, error) => {
        // RETRY ONLY IF ERROR error.errno == 215

        if (acc > 2) throw error;

        return acc + 1;
      }, 0),
      delay(1000)
    );
  }),
  catchError((error) => {
    console.log(error);

    // Here I want the use `throwError`

    return of({ error: error.response });
  })
);

Here is what I tried but unfortunately no idea how to combine scan counter and errno.

1 Answers

You can achieve that by moving the catchError operator to be before the retryWhen one, and by using take(3) operator to limit the retry attempts to 3 instead of using the scan one.

You can try something like the following:

this.httpService.post(url, data).pipe(
      tap(() => {
        console.log(`some debugging info`);
      }),
      map((response) => responseAdaptor(response)),
      catchError((error) => {
        // If the error is 215 then throw the error to trigger the retryWhen,
        // Otherwise return the error response.
        if (error.errno === 215) {
          return throwError(() => error);
        }
        return of({ error: error.response });
      }),
      retryWhen((errors) => errors.pipe(delay(1000), take(3)))
    );

This will complete the main Observable after 3 retry attempts. If you want to wrap the error and keep the main Observable working after 3 attempts, the observable returned by the retryWhen callback should return the following:

// This should be added directly after `take(3)` operator on the `errors` pipe.
concatMap((error) => of({ error: error.response })
Related