Почему мои Observables не подписаны в моем коде? - PullRequest
0 голосов
/ 01 октября 2019

Приведенный ниже код является реализацией метода intercept, который принадлежит интерфейсу HttpInterceptor. Этот конкретный код перехватывает каждый HTTP-запрос, исходящий из моего приложения, так что он может определить, что токен JWT, хранящийся в локальном хранилище браузера, является действительным. Если они есть, заголовки (токены аутентификации и авторизации) добавляются в HTTP-запрос, и запрос отправляется.

Я пытаюсь расширить код, чтобы перед добавлением заголовков код сначала проверялсячтобы гарантировать целостность JWT и чтобы он не истек или был изменен каким-либо образом. Если это так, то код должен получить новый токен JWT из конечной точки API, а затем проверить новый токен.

Проблема в том, что первая подписка, authTokenStream.pipe(take(1)).subscribe, кажется, никогда не срабатывает. Когда я перехожу через отладчик, каждая строка выполняется до этой, а затем после этого она никогда не переходит внутрь подписки. Вместо этого метод завершается, а затем снова начинается сверху для следующего HTTP-запроса.

Я думал, что это может быть как-то связано с микрозадачами и циклом событий, но в таком случае я бы ожидал, что код подписки будет фактически выполнен. Вместо этого код просто выполняет строки над ним и затем завершает его. Ни при каких условиях он не достигает точек останова внутри кода подписки.

Объект authTokenStream действителен, как я проверял в отладчике. Это не так, как будто это не определено или что-то еще.

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

    let jwtToken: string = this._authService.getAuthorizationToken();

    if (!this.checkJwtTokenIsValid(jwtToken)) { //Invalid token, get new one
      const authTokenStream = this._authService.getAuthorizationToken$();
      authTokenStream.pipe(take(1)).subscribe(newToken => {  //<-- Debugger gets to here and moves onto next HTTP request. 

        if(!this.checkJwtTokenIsValid(newToken)) //Still invalid
        {
          this._authService.signOut("jwtInvalid"); //Don't log out, get new token
          return;
        }

        req = this.addHeaders(req);
        return next.handle(req).pipe(
          catchError(error => {
            if (error instanceof HttpErrorResponse && error.status === 401) {
              this._authService.signOut("unauthorized");
            }
            if (error instanceof HttpErrorResponse && error.status === 403) {
              this._authService.signOut("expired");
            }
            return throwError(error);
          })
        );
      });
      return;
    }

    req = this.addHeaders(req);
    return next.handle(req).pipe(
      catchError(error => {
        if (error instanceof HttpErrorResponse && error.status === 401) {
          this._authService.signOut("unauthorized");
        }
        if (error instanceof HttpErrorResponse && error.status === 403) {
          this._authService.signOut("expired");
        }
        return throwError(error);
      })
    );

  }

getAuthorizationToken$(): Observable<string> {
    return this._httpClient.get<string>(this._configService.getConfig().tokenApi);
  }

1 Ответ

0 голосов
/ 01 октября 2019
  1. Если токен недействителен, после подписки ваш код всегда попадет в строку return;.

  2. Вы вернетесь изнутри subscribeметод, который является пустым методом. Так что ничего не произойдет, потому что ничто не подпишется на новый запрос.

Чтобы решить эту проблему, вам нужно настроить пропускающую асинхронную обработку.

if (!this.checkJwtTokenIsValid(jwtToken)) { //Invalid token, get new one
  const authTokenStream = this._authService.getAuthorizationToken$();

  return authTokenStream.pipe(
    take(1), 
    switchMap(newToken => {

    if(!this.checkJwtTokenIsValid(newToken)) //Still invalid
    {
      this._authService.signOut("jwtInvalid"); //Don't log out, get new token
      return EMPTY;
    }

    req = this.addHeaders(req);

    return next.handle(req).pipe(
      catchError(error => {
        if (error instanceof HttpErrorResponse && error.status === 401) {
          this._authService.signOut("unauthorized");
        }
        if (error instanceof HttpErrorResponse && error.status === 403) {
          this._authService.signOut("expired");
        }
        return throwError(error);
      })
    );
  }))
}

Оператор switchMap теперь подписывается на ваш tokenStream и возвращает наблюдаемый новый запрос. Таким образом, у канала запросов все еще есть запрос на подписку. Для получения дополнительной информации о switchMap здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...