在 Angular 可观察拦截器中使用来自 Promise 的值

Using Value from Promise inside Angular Observable Interceptor

我正在尝试使用 JWT 拦截器服务来验证用户对 Ionic 4 应用程序的 API 进行的每次调用。 我有一个看起来像这样的 JWT 拦截器

export class JwtInterceptor implements HttpInterceptor {
  constructor(private authenticationService: AuthenticationService) { }

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // add authorization header with jwt token if available
    let token = 'THE_JWT_HERE'
    if (token) {
      request = request.clone({
        setHeaders: {
          Authorization: `Bearer ${token}`
        }
      });
    }

    return next.handle(request);
  }
}

这可以静态地将令牌添加到正确的 header 到请求中。但是,我需要从 Ionic 存储中获取用户的实际 JWT,这是基于承诺的。

我认为它可能看起来像这样:

export class JwtInterceptor implements HttpInterceptor {
  constructor(private authenticationService: AuthenticationService) { }

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    // add authorization header with jwt token if available
    this.authenticationService.getJWT()
      .then(token => {
      if (token) {
        request = request.clone({
          setHeaders: {
            Authorization: `Bearer ${token}`
          }
        });
      }
    return next.handle(request);
  })
  }
}

这在编译时中断,因为我正在返回一个承诺,而不是一个可观察的。 但是,如果我将 return next.handle(request) 置于承诺之外,则不会添加任何授权 header。我明白为什么会这样,但我不确定解决方案。

如何从承诺中访问此值并在此拦截器中使用它?

您想使用一些 rxjs -- 一种方法可能是 switchMap:

import { switchMap } from "rxjs/operators"; 
import { from as observableFrom } from "rxjs";

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  return observableFrom(this.authenticationService.getJWT())
    .pipe(
      switchMap(token => {
        if (token) {
          request = request.clone({
            setHeaders: {
              Authorization: `Bearer ${token}`
            }
          });
        }
        return next.handle(request);
      })
    ); 
}

本质上,您想将该承诺转换为可观察的并将其合并到可观察的链中,从而导致 Observable<HttpEvent<any>> 拦截应该 return。

下一个合乎逻辑的问题是,有没有什么方法可以缓存 authenticationService 请求,并在请求中简单地使用缓存的值?我建议在服务中使用一种访问器模式,该模式在第一次请求令牌时查找令牌,然后简单地 returns 结果。如果您在每个 HttpRequest 之前执行 authenticationService 请求,它会显着降低您的请求速度。