You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用RxJS处理异步数据:登录后其他组件无法获取用户数据

问题:登录后其他组件无法获取用户数据,服务内却能正常获取

场景说明

我有一个loginComponent,接收邮箱和密码并发起HTTP请求获取用户数据,希望通过服务在其他组件中使用该用户数据。但登录后,需要使用用户数据的组件中得到的是null,服务中更新数据的方法里却能获取到用户数据。

登录组件代码

onRecievingResults(value:loginInterface){
  this.authService.saveData(value);
}

onLog(){
  this.onRecievingResults(this.loginUser)
  this.router.navigateByUrl('/stats/list')
}

服务代码

public currentUser:User | null = null;

private dataUserSource = new BehaviorSubject<User | null>(this.currentUser);
dataEmitter = this.dataUserSource.asObservable();

public saveData(value:loginInterface){
  this.loginUser(value).subscribe()
  this.dataUserSource.next(this.currentUser);
}

public loginUser(loginInterface: loginInterface | null){
  const url = `${this.basicURL}/login`
  const body = {email: loginInterface?.email, password1: loginInterface?.password1}
  return this.http.post<loginResponse>(url, body)
  .pipe(
    map(({user, token}) => this.setAuthentication(token, user)),
  catchError(err => throwError(() => err.error.message))
  )
}

private setAuthentication( token:string, user: User){
  this.currentState = authStatus.Authenticated
  this.currentUser = user
  localStorage.setItem('token', token)
  console.log(this.currentUser) //<-- 此处能获取到用户数据
  return true
}

其他组件代码

ngOnInit(): void {
  this.authService.dataEmitter.subscribe(data => console.log(data))
}

public currentUser:User | null = null

问题原因

核心问题是异步操作的执行顺序:

  • this.loginUser(value).subscribe() 是异步HTTP请求,调用后会立即执行后续代码,不会等待请求完成。
  • 所以this.dataUserSource.next(this.currentUser)会在HTTP请求返回、setAuthentication更新currentUser之前执行,此时currentUser还是初始的null。

解决方法

需要在HTTP请求成功完成后,再发送BehaviorSubject的更新通知,修改服务中的saveData方法:

public saveData(value:loginInterface){
  this.loginUser(value).subscribe({
    next: () => {
      // 请求成功后,currentUser已被setAuthentication更新,此时再发送通知
      this.dataUserSource.next(this.currentUser);
    },
    error: (err) => {
      // 处理登录失败的情况
      console.error('登录失败:', err);
    }
  });
}

也可以优化loginUser方法,让它直接返回用户数据,再在saveData中更新Subject,逻辑更清晰:

public loginUser(loginInterface: loginInterface | null){
  const url = `${this.basicURL}/login`
  const body = {email: loginInterface?.email, password1: loginInterface?.password1}
  return this.http.post<loginResponse>(url, body)
  .pipe(
    map(({user, token}) => {
      this.setAuthentication(token, user);
      return user; // 返回用户数据
    }),
    catchError(err => throwError(() => err.error.message))
  )
}

public saveData(value:loginInterface){
  this.loginUser(value).subscribe({
    next: (user) => {
      this.dataUserSource.next(user); // 直接用返回的user更新
    },
    error: (err) => {
      console.error('登录失败:', err);
    }
  });
}

内容的提问来源于stack exchange,提问作者Bayes-T

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 13:43:31