如何在 HttpInterceptor 中使用 NGXS 存储中的值?

Posted

技术标签:

【中文标题】如何在 HttpInterceptor 中使用 NGXS 存储中的值?【英文标题】:how to use value from NGXS store in HttpInterceptor? 【发布时间】:2018-12-24 14:37:51 【问题描述】:

我对 Angular 还是很陌生。我正在使用 Angular 6 和 NGXS 进行状态管理。

我的 NGXS 商店有一个user reducer,它的接口是

/* src/app/store/models/user.model.ts */
export interface User 
    serverToken? : string;
    // and other unrelated stuff

我想在HttpInterceptorAuthorization 标头中使用serverToken

这是我目前的HttpInterceptor 代码

import Store, Select from '@ngxs/store';
import Injectable from '@angular/core';
import HttpInterceptor, HttpHandler, HttpRequest, HttpEvent from '@angular/common/http';

import Observable from 'rxjs';
import User from '../store/models/user.model';

@Injectable()
export class ApiInterceptor implements HttpInterceptor 
    constructor(private store : Store) 
    @Select()user$ : Observable < User >;

    intercept(req : HttpRequest < any >, next : HttpHandler) : Observable < HttpEvent < any >> 
        let options = 
            url: `https://base-url.com/api/$req.url`
        ;

        const serverToken = '???';
        if (serverToken) // if not empty
            options = 
                ...options,
                headers: req
                    .headers
                    .set('Authorization', `JWT $serverToken`)
            

        const duplicate = req.clone(options);

        return next.handle(duplicate);
    

所以我的问题是:如果serverToken 不为空,如何正确优雅地使用user$ observable 来获取serverToken 并在HttpInterceptor 中使用它?

【问题讨论】:

【参考方案1】:

我最终使用了 NGXS 的 snapshot 功能。不确定这是否是最好的方法。 (快照功能在NGXS中可用,但在NGRX中不可用。我不知道如何在NGRX中解决这个问题)

在 user.state.ts 中

@State < User > (name: "user", defaults: )
export class UserState 
    // ... 

    @Selector()
    static serverToken(user : User) 
        return user.serverToken || '';
    

HttpInterceptor

    const serverToken = this
        .store
        .selectSnapshot(UserState.serverToken);

【讨论】:

【参考方案2】:

如果您更喜欢“可观察”的方法,请尝试以下方法:

intercept(req : HttpRequest < any >, next : HttpHandler) : Observable < HttpEvent < any >> 

  return this.serverToken$.pipe(
    take(1),
    concatMap(serverToken => 
      if (serverToken) 
        options = 
          ...options,
          headers: req.headers.set('Authorization', `JWT $serverToken`)
        
        const duplicate = req.clone(options);
        return next.handle(duplicate)
       else 
        // next() without changing req
        return next(req)
      
    
  )

您还需要定义一个返回用户令牌的@Selector 和来自拦截器类的@Select

注意:我不熟悉 HTTP 拦截器,只是根据我在 intercept() 的签名中看到的应用链接 RxJS 可观察对象的概念。

【讨论】:

以上是关于如何在 HttpInterceptor 中使用 NGXS 存储中的值?的主要内容,如果未能解决你的问题,请参考以下文章

从 Angular HttpInterceptor 调用 Promise

SnackBar 在 HTTPInterceptor 中使用时不显示

Angular 9 中用于刷新 jwt 令牌的 HttpInterceptor 问题

使用 HttpInterceptor 的 Angular 1.5 超时

使用 Angular 4.3 的 HttpInterceptor 拦截 HTTP 响应标头

当我在 HttpInterceptor 类中注入使用 HttpClient 的服务时,Angular 6 进入循环依赖的无限循环