BehaviorSubject не сразу меняет значение - PullRequest
0 голосов
/ 28 мая 2019

Я создаю пользовательскую службу входа с AuthGuard из Angular. У меня есть SessionService, у которого есть методы, такие как login() или onUserLoggedIn(), который в основном возвращает BehaviorSubject с текущим значением пользовательского статуса (вошел / не вошел в систему). На основе этого сервиса я создал реализацию сервиса AuthGuard implements CanActivate. Я вызываю метод onUserLoggedIn и проверяю текущее значение в теме. Проблема здесь в том, что в login значение метода изменяется после AuthGuard вызова onUserLoggedIn. Поэтому в первой попытке я получаю ложное значение от BehaviorSubject, но при второй попытке я получаю истинное значение.

Как я могу изменить реализацию этих двух сервисов для достижения текущей стоимости с первой попытки?

AuthGuard:

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot)
    : Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {

    console.log('auth');

    return this.sessionService.onUserLoggedIn()
      .pipe(
        map(res => {
          console.log('res', res);
          return res;
        }),
        take(1),
        tap(allowed => {
          console.log(allowed);
          if (!allowed) {
            this.router.navigate(['/login']);
          }
        })
      );
  }

SessionService:

private isLoggedIn = new BehaviorSubject(false);

  constructor(private apiService: ApiService) {
  }

  login(user: User): Observable<any> {
    console.log('hello before');
    return this.apiService.post(`${BASE_URL}/login`, user)
      .pipe(
        tap((token: Token) => {
          this.isLoggedIn.next(true);
          localStorage.setItem('token', token.token);
          console.log('hello');
        })
      );
  }

  onUserLoggedIn() {
    return this.isLoggedIn;
  }

Первая попытка идет со значением печати:

  • SessionService.ts: 19 привет до
  • AuthGuard.ts: 17 auth
  • AuthGuard.ts: 22 res false
  • AuthGuard.ts: 27 false
  • SessionService.ts: 25 привет

Второй (который я ожидаю быть первым):

  • SessionService.ts: 19 привет до
  • AuthGuard.ts: 17 аутентификаций
  • AuthGuard.ts: 22 res true
  • AuthGuard.ts: 27 true
  • SessionService.ts: 25 привет

Ответы [ 2 ]

1 голос
/ 28 мая 2019

Характер BehaviorSubject заключается в том, что он генерирует заданное значение немедленно при каждой подписке.

Таким образом, в зависимости от вашего варианта использования Subject.Также используйте оператор пропуска, чтобы пропустить первое значение.

return this.sessionService.onUserLoggedIn()
      .pipe(
        take(1),
        map(res => {
          console.log('res', res);
          return res;
        }),
        tap(allowed => {
          console.log(allowed);
          if (!allowed) {
            this.router.navigate(['/login']);
          }
        })
      );
  }

используйте startsWith(false) в других компонентах.

0 голосов
/ 28 мая 2019

Можете ли вы попытаться вернуть его как наблюдаемый?

onUserLoggedIn() {
        return this.isLoggedIn.asObservable();
      }
...