【问题标题】:BehaviorSubject in angular returning null角度返回 null 的 BehaviorSubject
【发布时间】:2020-02-25 03:53:35
【问题描述】:

我正在使用 BehaviorSubject 来存储登录时的用户信息。由于某些奇怪的原因,BehaviorSubject 返回的用户信息是 AuthGuard 中的null,它为我的端点激活。请帮助我了解我错过了什么。

我已经尝试将主题返回为可观察的,订阅主题 ReplaySubject。似乎没有任何效果,并且用户信息在身份验证保护中始终为空。我已经在 app 模块和服务组件之间移动了 AuthService 提供者声明。那也没有帮助。在调用 auth guard 之前,设置用户信息的流程是正常的。一旦调用 auth guard,用户信息就会丢失。

用户注册:这是用户登录的步骤

 onSubmit() {
    this.document.location.href = environment.callbackUrl;
  }

登录组件:该组件设置用户信息

this.authService.setUserInfo(user);
if (user.id_token!=null && user.role!=null && user.isLoggedIn){
  this.router.navigate(['/view-main/datalogger-list']);
}

认证服务

userSubject: BehaviorSubject<UserInfo> = new BehaviorSubject<UserInfo>(null);

setUserInfo(user: UserInfo){
  if(user && user !=null){
    this.userSubject.next(user);
  }
}

getUserInfo() {
    return this.userSubject.asObservable();
  }

auth guard:这里的用户信息为空

canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    debugger
    let userInfo:UserInfo;

    this.authService.getUserInfo().subscribe(user => {
      console.log('Evaluating in auth guard');
      console.log('User: ', user);
      //if user is logged in and role info is available from database.
      if(user && user!=null 
          && user.role!=null && user.role.trim().length>0 
          && user.wwid!=null && user.wwid.trim().length>0){
        // allow user
        userInfo = user;
        return true;
      }
      // TO-DO user logged in but do not have information from database -How i will knwo this?
      else if(user && user!=null 
              && user.wwid!=null && user.wwid.trim().length>0
              && (user.role==null || user.role=='undefined') ){
        this.router.navigate(['welcome']);
        return false;
      }else{
        // redirect user to oidc urls
        this.router.navigate(['welcome']);
        return false;
      }
    })
    return false;
  }

预期:返回当前用户信息 实际:返回 null

【问题讨论】:

  • this.document.location.href = environment.callbackUrl; 我认为这一行是从头开始重新加载应用程序。您确定您没有完全重新加载吗?在 Angular 中从一个页面导航到另一个页面时,您应该使用 Angular 路由器。
  • 你在哪里打电话setUserInfo(user)
  • 请分享更多代码或描述完整的上下文。很明显,您检索到 null 是因为即使在添加用户详细信息之前调用了 canActivate 保护。您需要对调用它的内容进行分类(页面加载?)
  • 对不起,canActivate 方法,正如你的定义所说,应该返回布尔值,而不是 UserInfo
  • @A.Chiesa,callbackUrl 是所有 IDP 和登录组件在调用后设置用户信息。所以我认为那里没有发生重新加载

标签: angular behaviorsubject canactivate


【解决方案1】:

谢谢大家。所有 cmets 都很有帮助,我的问题是身份验证服务在我的导航组件中被初始化。这就是它总是具有空值的原因。这个答案帮助我朝那个方向思考:Cannot pass data with service in angular2

【讨论】:

    【解决方案2】:

    我会说您的canActivate 方法中的问题的根源在于,在被调用的那一刻,您仍然没有用户的信息,并且您已经用 BehaviorSubject strong>null 值,这正是你得到的。

    我不会返回值,而是将 userSubject 作为 Observable 返回,并在您的 canActivate 方法上订阅它:

    userSubject: BehaviorSubject<UserInfo> = new BehaviorSubject<UserInfo>(null);
     setUserInfo(user: UserInfo){
        if(user && user !=null){
          this.userSubject.next(user);
        }
      }
     getUser() {
        return this.userSubject.asObservable();
      }
    

    还有守卫:

     canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    
        let userInfo:UserInfo;  
        this.authService.getUser().subscribe(user => userInfo = user);
        return true;
    }
    

    希望对你有帮助!

    ;)

    【讨论】:

    • 您在canActivate() 方法中错过了返回,并且 userInfo 的等式不是等式而是赋值
    • 你不能订阅 BehaviorSubject 吗?为什么我们这里需要“asObservable()”?
    • @DanielHabenicht,不,我没有错过。我刚刚修改了提供的示例,它没有返回任何内容。我认为它没有完成,他还想在返回之前为用户做一些事情......
    • @SergeyRudenko 通常的做法是不公开主题,并在服务中将其保持为私有。暴露 Observable,您将不再需要手动 complete BehaviorSubject,并将其用作其他 Observable。
    • 是的,我明白了,但它不是有效的代码。看你的例子的人会遇到下一个错误,因为 canAccticate 从不返回任何东西。你能在你的代码中添加“do something with it”作为注释并使其有效吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-04
    • 1970-01-01
    • 2022-01-19
    • 1970-01-01
    相关资源
    最近更新 更多