0

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.

2
  • Aren't you doing this already with .catch(err => this.handleHttpError(err))? Or what this method returns? Commented May 14, 2018 at 19:11
  • hmm. Well loosely. I catch the error, but I can't figure out how to throw an HttpResponse from the err Observable that is given to the retryWhen() .. what is thrown is an observable of err I believe. Commented May 14, 2018 at 19:28

2 Answers 2

4

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

Sign up to request clarification or add additional context in comments.

2 Comments

the subscription is handled in a different part of the Angular app and it is functioning correctly. The issue that I have is getting the httpResponse object that accompanied the error after the retry. I can't seem to find a way to do that from the err observable that is sent to the retryWhen from the httpClient. Does that make better sense?
So you want to send the error from retryWhen as next or error notification?
-1

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.

1 Comment

I am having the same issue, are you still using this method? I tried it but I get an error for .do function (says not available)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.