I have the following code in an interceptor:
intercept(request: HttpRequest<any>, next: HttpHandler): any {
return next.handle(request).pipe(
catchError(async error => {
if (error instanceof HttpErrorResponse && (error.status === 302 || error.status === 401 || error.status === 403)) {
this.store.dispatch(new Authenticate());
try {
await firstValueFrom(this.store.pipe(
select(selectAuthCallState),
filter(state => state === ProcessState.COMPLETED),
take(1)
));
} catch (err) {
return throwError(async () => new Error(error.message));
}
}
return next.handle(request);
})
);
}
- When a HTTP request is getting a 401 error (for instance), it gets into the
catchError
block as expected. this.store.dispatch(new Authenticate());
is dispatching an authentication event, which works as expected.- Then, in order to detect the authentication completion, I'm awaiting the action to finish (by
await
ing the selector update) - works perfectly. - I'm then trying to recall the original request (which was rejected by the lack of authentication), and nothing happens.
What am I doing wrong?
Thanks!
CodePudding user response:
I notice some bugs, Im not should that fixing them would fix your app
- lack of async before interceptor
- this rxjs's pipe doesn't have any retryWhen or retry (check this tutorial)
CodePudding user response:
Here's the solution I came up with. Should be switched to retry
instead of deprecated retryWhen
.
intercept(request: HttpRequest<any>, next: HttpHandler): any {
return next.handle(request).pipe(
retryWhen(errors => {
let count = 0;
return errors.pipe(
takeWhile(_ => count <= this.RETRY_COUNT),
concatMap(async (error) => {
if (error instanceof HttpErrorResponse &&
(error.status === 302 || error.status === 401 || error.status === 403)
) {
this.store.dispatch(new Authenticate());
await firstValueFrom(this.store.pipe(
select(selectAuthCallState),
filter(state => state === ProcessState.COMPLETED),
take(1)));
return of(error);
}
return throwError(() => new Error(error.message));
}),
);
})
);
}