Dave S.
Dave S.

Reputation: 183

handling error from Angular httpClient retryWhen block

I have a pretty simple http call happening. Upon error I want the request to retry 3 times with a three second delay between retries. I have worked out a solution that is close:

return this.http.put<string>(URL,
               value).retryWhen(err => {
                    return err
                    .delay(3000)
                    .take(3)
                    .concat(Observable.throw("error occurred"));
                })
               .catch(err => this.handleHttpError(err)) ;

The client retries three times like I expect. However, I don't know how to throw the final error in such a way that my error handler (which normally expects an HttpResponse argument) can process the error.

Once I have taken(3) how can I get the final error, and convert it to an HttpResponse to send to my handler? Or am I looking at this the wrong way?

I need to know, at the end of the day, the HttpResponse that accompanied the error(s). When I throw the err from the retryWhen at the concat function that doesn't seem to accomplish it.

I am betting this is a pretty common thing to do, but being newer to Angular 5 and react I think I am just missing the boat.

Upvotes: 0

Views: 2435

Answers (2)

Dave S.
Dave S.

Reputation: 183

For anyone who runs into this, I was able to capture the httpErrorResponse by slightly changing the return:

first I added a local var

let httpError: HttpErrorResponse = null;

then I modified the return:

 return error
          .do(err => {if (err instanceof HttpErrorResponse) {httpError = err; }})
          .delay(3000)
         .take(5)
         .concat(Observable.throw(error));
      })

this allows me to cache the last http error response. I then look for this in the catch and work accordingly. Seems to be working just fine.

Upvotes: -1

martin
martin

Reputation: 96959

You can use concatMap to count how many times you've tried to resubscribe and according to that send next or error notifications (this means re-throwing the error in the inner observable that is propagated further).

Observable.throw(42)
  .retryWhen(err => err
    .do(console.info) // remove, prints 42
    .delay(3000)
    .concatMap((error, index) => {
      if (index === 2) {
        return Observable.throw("error occurred"); // or Observable.throw(error);
      }
      return Observable.of(null);
    })
  )
  // .catch(err => handleHttpError(err))
  .subscribe(
    v => console.log('next', v), // not called
    e => console.log('error handler', e),
  );

This prints the following output:

42
42
42
error handler: error occurred

See live demo: https://stackblitz.com/edit/rxjs5-jt5ald

Upvotes: 4

Related Questions