【问题标题】:How do I get a value in a BehaviorSubject to return within a getter?如何获取 BehaviorSubject 中的值以在 getter 中返回?
【发布时间】:2020-09-15 14:57:21
【问题描述】:

据我了解,当您订阅 BehaviorSubject 时,该订阅是异步的。我正在尝试从 BehaviorSubject 中的对象获取值并在 getter 中返回该值。 getter 需要返回类型“数字”。我该如何处理?

下面,我有一个 getter userId,它应该从 BehaviorSubject _loggedInUser 中保存的对象返回用户 ID

export class AuthServiceService {

  private _loggedInUser: BehaviorSubject<LoggedInUserData> = new BehaviorSubject(null);

  constructor(
    private http: HttpClient, 
    private storage: Storage
  ) { }


 /// This method below!!! --------------

  public get userId(): number{

    this._loggedInUser.pipe(
      take(1), 
      map(((loggedInUserData: LoggedInUserData) => {
        if(loggedInUserData){
          return loggedInUserData.user_id
        }
        return null;
      }))
    ).subscribe((userId: number | null) => {
      return userId;
    });
    
  }
  
 //// -----------------


  public doLogin(loginData: LoginFormData): Observable<any>{

    return this.http.post<LoggedInUserData>(`${authURL}/token`, loginData)
    .pipe(
      catchError(err => {

        if(err.status && err.status === 403)
          return throwError('The credentials you have entered are invalid or do not exist.');
        else
          return throwError('There was an issue processing your request.');

      }), 
      tap(respData => {

        console.log('LOGGED IN USER DATA: ', respData);

        this._loggedInUser.next(respData);
        this.storage.set('userData', respData);

      })
    );



  }


  public async autoLogin(){



  }


  public doLogout(){




  }





}

【问题讨论】:

  • 你试过_loggedInUser.value.user_id吗? BehaviorSubject 实例有一个value 属性,它给出了最新的值。 rxjs-dev.firebaseapp.com/api/index/class/BehaviorSubject
  • 在这种情况下,我是否应该使用 BehaviorSubject 来保存用户数据?
  • BehaviorSubject 是有目的的。如果您不需要它,请不要使用它。您可以根据需要组合各种 observables。
  • “我是否应该使用BehaviorSubject 来保存用户数据?”如果您需要在组件中访问数据,这将很有用
  • 你的用户数据是异步加载的,所以你要问自己:如果有人想访问userId(),但还没有数据,如果有人在@时收到null,可以吗? 987654328@ 即使在 5 毫秒后出现用户 ID 也会被调用?当我们想要访问数据并且如果它不存在时,我们使用 Observables 等到它存在或对更改的数据做出反应。使用 Observables 意味着从许多函数中返回 Observables,并且仅在我们需要实际数据时订阅。在大多数情况下,您希望 userId() 返回一个 Observable。

标签: javascript angular ionic-framework rxjs


【解决方案1】:

拥有Subject的访问权限,可以通过getValue()方法同步获取其值,如下:

public get userId(): number {
  return this._loggedInUser.getValue()?.userId
}

【讨论】:

    【解决方案2】:

    如果您只需要同步结果,则应使用 Rafi Henig 提供的示例:

        public get userId(): number {
          return this._loggedInUser.getValue()?.userId
        }
    

    如果你希望它是异步的,你可以返回一个Observable&lt;number&gt;,如果你需要在那里显示它,你可以在你的 html 中使用一个异步管道。如果没有,您可以在需要的地方订阅该 Observable,或者如果您想跟踪值的更改,请保留订阅。我不确定这是否是你想要的,但这里有一个例子:

      public get userId(): Observable<number> {
        return this._loggedInUser.pipe(
          map((item) => item?.userId)
        );
      }
    

    对于 HTML,使用:{{ userId | async }},对于打字稿代码,您可以使用:

        this.userId.pipe(take(1)).subscribe((userId) => {
          console.log(userId);
        });
    

    如果您想跟踪打字稿中的更改,您应该删除 take(1) 并简单地将 subscribe 删除。记得清理ngOnDestroy中的订阅。

    【讨论】:

    • pluck 而不是 map this._loggedInUser.pipe(pluck('userId')) 会更有意义
    • @Stavm pluck 将在 v7 中弃用并在 v8 中删除,因此使用 map 也不错。
    【解决方案3】:

    另一种方法 - 将 Observable 转换为 Promise,然后使用 async/await:

    const user = await this._loggedInUser.toPromise();
    return user && user.userId;
    

    【讨论】:

    • 虽然,我不认为你可以有一个异步 getter。
    • 是的,错过了。无论如何,根据getter中的大量代码,就我而言,最好将其转换为方法......但取决于你:-)。请改用 getValue()。
    猜你喜欢
    • 1970-01-01
    • 2019-06-24
    • 1970-01-01
    • 1970-01-01
    • 2018-10-27
    • 2018-02-09
    • 1970-01-01
    • 2023-02-09
    • 2020-03-08
    相关资源
    最近更新 更多