BehaviorSubject不会立即更改值

时间:2019-05-28 08:52:53

标签: angular typescript rxjs observable guard

我正在使用AuthGuard中的Angular创建自定义登录服务。我有一个SessionService,它具有诸如login()onUserLoggedIn()之类的方法,这些方法基本上会返回BehaviorSubject并带有当前用户状态值(已登录/未登录)。基于此服务,我创建了AuthGuard implements CanActivate服务的实现。我调用onUserLoggedIn方法并检查subject中的当前值。这里的问题是在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身份验证
  • AuthGuard.ts:22 res false
  • AuthGuard.ts:27错误
  • SessionService.ts:25你好

第二个(我希望是第一个):

  • SessionService.ts:19之前您好
  • AuthGuard.ts:17身份验证
  • AuthGuard.ts:22 res true
  • AuthGuard.ts:27是
  • SessionService.ts:25你好

2 个答案:

答案 0 :(得分:1)

BehaviorSubject的本质是,只要您订阅,它就会立即发出给定值。

因此,根据您的用例使用主题。也可以使用skip运算符跳过第一个值。

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)

答案 1 :(得分:0)

您可以尝试将其返回为可观察状态吗?

pipeline.fit(train_x, train_y)