【问题标题】:angular refresh token interceptor with http.get call instead of rxjs of operator使用 http.get 调用而不是操作员的 rxjs 的角度刷新令牌拦截器
【发布时间】:2021-07-30 04:30:54
【问题描述】:

我正在尝试实现这个angular refresh token interceptor(也来自this stackoverflow),但是在将 refreshToken 函数更改为返回 this.http.get 观察者而不是 rxjs of 时遇到问题strong> 运算符。

它与 of 一起工作正常,但是一旦我更改为 http.get return 它就不会触发 get 调用并且不会发出任何东西,也不会进入下一个concat 观察者订阅。

无法弄清楚为什么它不起作用。任何帮助表示赞赏。

拦截器文件:

export class CaughtInterceptor implements HttpInterceptor {
  constructor(private authService: AuthService) {
  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    let retries = 0;
    return this.authService.token$.pipe(
      map(token => req.clone({ setHeaders: { Authorization: `Bearer ${token}` } })),
      concatMap(authReq => next.handle(authReq)),
      // Catch the 401 and handle it by refreshing the token and restarting the chain
      // (where a new subscription to this.auth.token will get the latest token).
      catchError((err, restart) => {
        // If the request is unauthorized, try refreshing the token before restarting.
        if (err.status === 401 && retries === 0) {
          retries++;

          return concat(this.authService.refreshToken$, restart);
        }

        if (retries > 0) {
          this.authService.logout();
        }

        return throwError(err);
      })
    );
  }
}

auth.service 文件:

export interface RefreshTokenResult {
  accessToken: string;
}

@Injectable()
export class AuthService {
  private tokenSubject$ = new BehaviorSubject<string | null>(null);

  token$ = this.tokenSubject$.pipe(
    filter((token) => token !== null),
    take(1)
  );

  refreshToken$: Observable<any> = defer(() => {
    if (this.tokenSubject$.value === null) {
      return this.token$;
    }
    // Defer allows us to easily execute some action when the Observable
    // is subscribed. Here, we set the current token to `null` until the
    // refresh operation is complete. This ensures no requests will be
    // sent with a known bad token.
    this.tokenSubject$.next(null);

    return this.refreshToken().pipe(
      tap((res) => {
        this.tokenSubject$.next(res.accessToken);
      }),
      catchError((err) => {
        this.logout();
        throw err;
      })
    );
  });

  get token(): string | null {
    return this.tokenSubject$.value;
  }

  authenticate(): void {
    this.tokenSubject$.next('someToken');
  }

  refreshToken(): Observable<RefreshTokenResult> {
    // Changed of to this.http.get here
    return this.http.get<RefreshTokenResult>(url).pipe(delay(0));

      /*
      return of({
        accessToken: 'newToken',
      }).pipe(
        delay(0),
      );
      */
  }

  logout(): void {}
}

【问题讨论】:

  • 任何控制台错误?也许您为了简洁而省略了它,但我看不到您将http 注入 auth.service 的位置,以便您可以使用 this.http

标签: angular rxjs


【解决方案1】:

HttpClient 返回的 Observables 是冷的 observables。这意味着,只有当您订阅该 observable 或管道时才会发出请求。我不确定您需要在哪里订阅,但这就是没有请求的原因。

【讨论】:

  • 是的,一定是它,认为 concat 会订阅,但它不会与 httpclient 冷观察。我重构并采用了不同的解决方案,因为代码最后感觉很乱。感谢您的帮助。
猜你喜欢
  • 2019-07-09
  • 1970-01-01
  • 2020-05-12
  • 2020-02-10
  • 2019-01-21
  • 1970-01-01
  • 2022-11-03
  • 1970-01-01
  • 2021-02-11
相关资源
最近更新 更多