【问题标题】:How to retrieve data from an Observable and use it in an Interceptor?如何从 Observable 中检索数据并在 Interceptor 中使用它?
【发布时间】:2020-02-05 19:06:52
【问题描述】:

我正在Angular 8 中构建应用程序的前端。此应用程序使用OAuth 2 实现来管理身份验证(密码授予),因此任何HTTP 请求(令牌端点的请求除外)都需要在其标头上包含有效的access_token。

为了提供上述令牌,我创建了一个Angular interceptor,它从另一个服务中检索令牌,然后将其附加到截获的HTTP 请求中。令牌检索方法不直接给出令牌,而是最终解析为有效令牌的可观察对象,我做出此选择是因为访问令牌可能不会立即可用,如果令牌过期,应用程序需要使用 @ 刷新它987654326@ 调用,然后可以将刷新的令牌传递给HTTP 拦截器。

我遇到的问题是,尽管我尝试了很多次,但拦截器并没有等待获取令牌,所以最后拦截器被跳过,HTTP 请求是在没有附加任何令牌的情况下发出的。

这是我的拦截器的代码,retrieveValidToken 是返回令牌的Observable

import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
import { FacadeService } from './facade.service';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class HttpInterceptorService implements HttpInterceptor {

  constructor(private facadeService: FacadeService) { }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (req.url.includes('localhost:3000') && !req.url.endsWith('token')) {
      this.facadeService.retrieveValidToken()
        .subscribe(
          (res) => {
            const clone = req.clone({ setHeaders: { Authorization: `Bearer ${res}` } });
            return next.handle(clone);
          },
          (err) => {
            const clone = req.clone({ setHeaders: { Authorization: `Bearer ` } });
            return next.handle(clone);
          }
        );
    } else {
    return next.handle(req);
    }
  }
}

【问题讨论】:

    标签: javascript angular typescript rxjs


    【解决方案1】:

    问题是 'intercept' 方法应该立即返回 observable,所以不要订阅 'this.facadeService.retrieveValidToken()' 使用以下代码:

    return this.facadeService.retrieveValidToken().pipe( mergeMap(token => next.handle(req.clone({ setHeaders: { Authorization: 'Bearer ${token}' })) ) )

    【讨论】:

      【解决方案2】:

      Observables 是异步的。 subscribe 方法外面的代码不会等待里面的代码。

      你应该返回 observable 本身,而不仅仅是它订阅中的结果:

        intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
          if (req.url.includes('localhost:3000') && !req.url.endsWith('token')) {
            return this.facadeService.retrieveValidToken()
              .subscribe(
                res => {
                  const clone = req.clone({ setHeaders: { Authorization: `Bearer ${res}` } });
                  return next.handle(clone);
                }
              );
          } else {
          return next.handle(req);
          }
        }
      

      类似的东西:

      How use async service into angular httpClient interceptor

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-01-20
        • 1970-01-01
        • 2018-01-28
        • 2020-10-12
        • 2016-02-21
        • 1970-01-01
        • 2021-06-27
        相关资源
        最近更新 更多