Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 RxJS Observable: RetryWhen filter retry on error Status

I am using Angular 2 HTTP library which returns an observable. I want to implement retry on certain error status/code.

I have an issue, if the error is not 429, Observable.of(error) is getting executed in error case to retry, but when all your 2 retry fails the execution of flow goes to success block instead of catch block.

How to make execution of flow to catch block in all retry fails?

    return this.http.get(url,options)
           .retryWhen((errors) => {
                      return errors
                            .mergeMap((error) => (error.status === 429) ? Observable.throw(error) : Observable.of(error))
                            .take(2);
                     })
                       .toPromise()
                       .then((res:Response) => console.log('In Success Block'))
                       .catch((res) => this.handleError(res));

will it resolve my problem

        return this.http
  .post(url, JSON.stringify(body), requestOptions).retryWhen((errors) => {
    return errors
      .mergeMap((error) => (error.status === 404) ? Observable.throw(error) : Observable.of(error))
      .take(2);
  }).map((res:Response) =>{
    if (res.status === 200)
      return res;
    else
      return Observable.throw(res);
  })
  .toPromise();
like image 869
sulabh rastogi Avatar asked Oct 08 '16 02:10

sulabh rastogi


1 Answers

A little late to the party but, I recently implemented a similar behaviour. Here is my solution:

  post<T>(serviceUrl: string, data: any): Observable<T> {
    return Observable.defer(() => {
        return super.post<T>(serviceUrl, data);
    }).retryWhen((error) => {
        return this.refresh(error);
    });
}

And the refresh function:

refresh(obs: Observable<any>): Observable<any> {
    return obs
        .switchMap((x: any) => {
            if (x.status === 401) {
                return Observable.of(x);
            }
            return Observable.throw(x);
        })
        .scan((acc, value) => {
            return acc + 1;
        }, 0)
        .takeWhile(acc => acc < 3)
        .flatMap(() => {
            console.log('Token refresh retry');
            return this.tokenRefreshService.refreshToken();
        });
}

The use case is that whenever I make an HTTP request and get a 401 response, I want to do a token refresh and then retry the initial request with the new token. When a 401 occurs I use switchMap to return a new Observable, otherwise, I return an Observable.throw(x) that stops the retry logic from being executed.

And the calling code looks like this (where error is called whenever you return an Observable.throw(x)):

 this.http.post(x).subscribe(response => {
      ...
        }
    }, error => {
        ...
        }
    });
like image 73
Radu Cojocari Avatar answered Oct 22 '22 04:10

Radu Cojocari