Секвенирование цепочки RXJS / обработка наблюдаемых NGRX в HttpInterceptor - PullRequest
1 голос
/ 02 июля 2019

У меня проблемы с подключением токена доступа JWT к заголовку HTTP-запроса в классе, производном от базового класса HttpInterceptor (Angular 8).

Я сузил вопрос до последовательности, в которой операции выполняются внутри 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.

1 Ответ

0 голосов
/ 02 июля 2019

Вы можете рассмотреть возможность использования оператора 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);
      })
    );
  }
}

Некоторые ресурсы по теме:

...