首页 > 解决方案 > 在 Angular Observable 拦截器中使用 Promise 中的值

问题描述

我正在尝试使用 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);
  }
}

这可以静态地将令牌添加到请求的正确标头中。但是,我需要从基于承诺的 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)承诺之外,则不会添加授权标头。我理解为什么会发生这种情况,但我不确定解决方案。

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

标签: angularpromiseobservableangular7ionic4

解决方案


你想使用一些 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>>拦截应该返回。

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


推荐阅读