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

how to use value from NGXS store in HttpInterceptor?

我是 Angular 的新手。我正在使用 Angular 6 和 NGXS 进行状态管理。

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

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

我想在 Authorization header 中使用 serverToken HttpInterceptor

这是我当前的 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);
    }
}

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

我最终使用了 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);

如果您更喜欢 "observable" 的方法,请尝试类似的方法:

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 returns 用户令牌和 @Select 来自拦截器的 class。

注意:我不熟悉 HTTP 拦截器,只是根据我在 intercept().

的签名中看到的内容应用链接 RxJS 可观察对象的概念