Вы можете исправить это поведение ошибки, подключив setToken
к возвращаемому наблюдаемому с помощью оператора retryWhen
. Таким образом, renewToken
и setToken
не будут выполняться параллельно И, что более важно, setToken
будет приниматься во внимание цепочкой перехватчика в КАЖДОМ запросе.
intercept(req: HttpRequest<any>, next: HttpHandler) {
const authservice = this.injector.get(AuthService);
return of(req).pipe(
switchMap((req) => {
return authservice.setToken() // Gets the token. *should rename this method to getToken()
.pipe(
map(token => { // Set the token.
const tokenreq = req.clone({
setHeaders: {
Authorization: `Bearer ${authservice.setToken()}`
}
});
return tokenreq;
})
),
switchMap(tokenreq => next.handle(tokenreq)), // Execute next interceptor and eventually send the request.
retryWhen(errors => errors.pipe(
mergeMap((err: HttpErrorResponse, i: number) => {
authservice.invalidateToken() // Invalidate token. Erase token or expires it.
if (error.error.message == 'The incoming token has expired') {
return of(err); // will start the current pipe all over again - and get the token once again.
}
return throwError(error);
})
)
)
}
Пояснение:
В вопросе setToken
не подключен к цепочке наблюдаемых, которые возвращаются методом перехватчиков. Последовательность выполнения кода до:
1) interceptor method execution -> setToken() -> return observable
2) request asked by http.get(..) -> chain of observables return by interceptors -> request sent -> chain of observables
И в этом ответе:
1) interceptor method execution -> setToken() -> return observable
2) request asked by http.get(..) -> chain of observables return by interceptors and setToken() inside one! -> request sent -> chain of observables
Примечание: метод
setToken
должен возвращать наблюдаемый с токеном и invalidateToken
должен иметь возможность удалить токен.
Это может быть легко достигнуто с помощью:
private token$: AsyncSubject<string>;
getToken(): Observable {
if (!token$) this.token$ = new AsyncSubject();
getTokenOperation.subscribe(t => {
this.token$.next(t);
this.token$.complete();
})
return this.token$.asObservable();
}
invalidateToken() {
this.token$ = null;
}