在拦截器中管理订阅。角

问题描述 投票:0回答:1

我想编写刷新 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) 但它不起作用,因为拦截器是异步的。

angular interceptor
1个回答
0
投票

鉴于您的订阅位于角度拦截器服务内,如果有可能,您可以使用 ngOnDestroy 并取消订阅其中的任何订阅。可能需要的唯一更改是声明可观察的单独。

© www.soinside.com 2019 - 2024. All rights reserved.