Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular + RxJS: repeat the request on status code 202

Tags:

angular

rxjs

I have a simple request that I would like to repeat in case the response is with status 202. Currently, it looks like this:

this.http.get(endPoint, {
    withCredentials: true,
    headers: this.headers
})
.map((response: Response) => {
    return response.text() ? response.json() : '';
})
.catch((error) => this.handleError(error));

I have tried with .repeatWhen() but unfortunately, I don't receive the Response object and I cannot set a validation by the status code.

Any ideas how can I do that?

like image 767
Hristo Eftimov Avatar asked Aug 07 '17 09:08

Hristo Eftimov


2 Answers

That's a misunderstanding of how repeatWhen() works. The callback to this operator receives a single parameter which is an Observable where it pushes an empty item when the source completes. So it's not ideal for you (because you don't have access to the Response object you need).

You could use retryWhen() instead:

this.http.get(endPoint, { withCredentials: true, headers: this.headers })
    .map((response: Response) => {
        if (response.code === 202) {
            throw response;
        }
        return response;
    })
    .map((response: Response) => {
        return response.text() ? response.json() : '';
    })
    .retryWhen(obs => {
        return obs; // always just resubscribe without any further logic
    });

This throws the response as an error which is then caught by retryWhen that just resubscribes. You could of course use more logic to control if you resubscribe, for example:

.retryWhen(obs => {
   return obs.filter(...);
});
like image 92
martin Avatar answered Nov 16 '22 03:11

martin


Use this for Rx 6. This retries the 202 up to 3 times, and throws a timeout error at the end of the third try.

@Injectable()
export class ProgressInterceptor implements HttpInterceptor {
    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

        return next.handle(req).pipe(
            map(t => {
                if (t['status'] === 202) {
                    throw 202;
                }
                return t;
            }),
            retryWhen(t => {
                return t.pipe(
                    concatMap((e, i) => {
                        if (e !== 202) {
                            return throwError(e);
                        }
                        return iif(
                            () => i >= 2,
                            throwError(new Error('Operation Timed Out!')),
                            of(e).pipe(delay(1000))
                        )
                    })
                )
            }),
        );    
    }
}
like image 40
pixelbits Avatar answered Nov 16 '22 03:11

pixelbits