我想编写刷新 JWT 令牌的拦截器。问题是:我应该如何取消订阅 return this.authService.refreshToken(token)?我理解对吗? switchMap 只取消订阅内部可观察的内容,并且不会触及外部(我的意思是 this.authService.refreshToken(token) )。这里是代码:
// SERVICE
refreshToken(token: string) {
return this.http.post(AUTH_API + 'refreshtoken', {
refreshToken: token
}, httpOptions);
}
}
// Interceptor
export class AuthInterceptor implements HttpInterceptor {
private isRefreshing = false;
private refreshTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(null);
constructor(private tokenService: TokenStorageService, private authService: AuthService) { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<Object>> {
let authReq = req;
const token = this.tokenService.getToken();
if (token != null) {
authReq = this.addTokenHeader(req, token);
}
return next.handle(authReq).pipe(catchError(error => {
if (error instanceof HttpErrorResponse && !authReq.url.includes('auth/signin') && error.status === 401) {
return this.handle401Error(authReq, next);
}
return throwError(error);
}));
}
private handle401Error(request: HttpRequest<any>, next: HttpHandler) {
if (!this.isRefreshing) {
this.isRefreshing = true;
this.refreshTokenSubject.next(null);
const token = this.tokenService.getRefreshToken();
if (token)
return this.authService.refreshToken(token).pipe( // Question here!!!
switchMap((token: any) => {
this.isRefreshing = false;
this.tokenService.saveToken(token.accessToken);
this.refreshTokenSubject.next(token.accessToken);
return next.handle(this.addTokenHeader(request, token.accessToken));
}),
catchError((err) => {
this.isRefreshing = false;
this.tokenService.signOut();
return throwError(err);
})
);
}
return this.refreshTokenSubject.pipe(
filter(token => token !== null),
take(1),
switchMap((token) => next.handle(this.addTokenHeader(request, token)))
);
}
我尝试过使用管道 take(1) 但它不起作用,因为拦截器是异步的。
鉴于您的订阅位于角度拦截器服务内,如果有可能,您可以使用 ngOnDestroy 并取消订阅其中的任何订阅。可能需要的唯一更改是声明可观察的单独。