【问题标题】:Sequencing RXJS chaining / processing of NGRX observables in an HttpInterceptor在 HttpInterceptor 中对 NGRX 可观察对象的 RXJS 链接/处理进行排序
【发布时间】:2019-11-13 00:32:30
【问题描述】:

在派生自 HttpInterceptor (Angular 8) 基类的类中,我无法将 JWT 访问令牌附加到 HTTP 请求的标头。

我已将问题缩小到在 Http 拦截器中执行操作的顺序。在令牌从 NGRX 存储(异步)返回之前,请求似乎已发送给调用方。

我不清楚如何确保仅在从 NGRX 存储区收到令牌后才返回请求。

export class ServerInterceptor implements HttpInterceptor, OnDestroy {

    private state$: Observable<any>;
    private unsubscribeAll: Subject<any>;

    constructor(
        private store: Store<AuthenticationState>
    ) {
        this.unsubscribeAll = new Subject();
        this.state$ = this.store.select(getAccessToken);
    }

    ngOnDestroy(): void {
        this.unsubscribeAll.next();
        this.unsubscribeAll.complete();
    }

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

        const output = next.handle(request).pipe(
            takeUntil(this.unsubscribeAll),
            withLatestFrom(
                this.store.select(selectAuthenticationState), (_action, state) => {
                    console.log(state.accessToken);
                    if (state.accessToken) {
                        request = request.clone({
                            setHeaders: {
                              Authorization: `Bearer ${state.accessToken}`
                            }
                          });
                    }
                    console.log('1');
                    return request;
                }
            ),
            switchMap((req) => {
                console.log('2');
                return next.handle(req);
            }),            
        );
        console.log('3');
        return output;
    }
}

控制台的输出按3、1、2的顺序处理拦截器,应该是1、2、3处理。

【问题讨论】:

    标签: angular rxjs ngrx


    【解决方案1】:

    您可以考虑将select 运算符与您的选择器getAccessToken 和“链”可观察对象一起使用。
    如果您使用first()take(1) 运算符,则无需订阅。 Observable 会在一个值后自动完成。

    HttpInterceptor 的代码如下所示:

    export class ServerInterceptor implements HttpInterceptor {
    
      constructor(
        private store: Store<AuthenticationState>
      ) {}
    
      intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        return this.store.pipe(
          select(getAccessToken),
          first(),
          mergeMap(accessToken => {
    
            const authReq = !!accessToken ? request.clone({
              headers: request.headers.set('Authorization', `Bearer ${accessToken}`)
            }) : request;
    
            return next.handle(authReq);
          })
        );
      }
    }
    

    有关该主题的一些资源:

    【讨论】:

    • 这就像一个魅力。你是一个超级明星。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2020-12-22
    • 2018-10-25
    • 2018-04-11
    • 2023-03-31
    • 2021-11-05
    • 1970-01-01
    • 2018-06-07
    • 2020-12-25
    相关资源
    最近更新 更多