繁体   English   中英

如何轻松地将Observable转换或分配给行为主题,以便其他组件可以共享它

[英]How to easily convert or assign an Observable to a Behavior Subject, so other component can share it

我是Observable样式编程的新手。 我有一个问题:我希望在组件之间跨应用程序共享用户信息 - 我使用BehaviorSubject来共享此信息。 这是通过将BehaviorSubject共享为AuthInfo来启发的。 如果我可以在我的应用程序组件中共享包含uid的AuthInfo,为什么我可以使用它来共享我的用户对象数据?

问题是,用户对象,我是从Firebase获得的。 所以它是一个Observable,我不知道如何将它分配给一个行为主题。 所以这是我尝试的代码:

  @Injectable()
  export class AuthService {

  static UNKNOWN_USER = new AuthInfo(null);

  static EMPTY_USER = new User(null, null, null, null);

  authInfo$: BehaviorSubject<AuthInfo> = new BehaviorSubject<AuthInfo>(AuthService.UNKNOWN_USER);

  userInfo$: BehaviorSubject<User> = new BehaviorSubject<User>(AuthService.EMPTY_USER);

  constructor(private auth: FirebaseAuth, private db:AngularFireDatabase, @Inject(FirebaseRef) fb) {

//firebase way to see if user is login or not
this.auth.subscribe(user => {
  if (user) {
    const authInfo = new AuthInfo(user.uid);
    this.authInfo$.next(authInfo);
    //This is the part I do not know how to do
    [OPTION 1]: this.userInfo$.next(findUserByuid(user.uid)) ?? - error
    [OPTION 2]: this.userInfo$ = findUserByuid(user.uid) ?? - userInfo$ turn into an observerable, which when I logout to call this.userInfo$.next(AuthService.EMPTY_USER) it will  throw error as .next() is not a function.
    [OPTION 3]:
    this.findUserByuid(user.uid).subscribe(user => {
      this.userInfo$.next(user);
    });
    ---- Can I put a subscribe inside of another subscribe to chain it like promise? I am not sure this is following the best practices. But this is the only option that there is no error. But just not sure I am doing it right. I do get the user object no problem

  }
  else {
    this.authInfo$.next(AuthService.UNKNOWN_USER);
  }
});


}

findUserByuid(uid:string):any {
   //return a firebase object observerable
   return this.db.object('userProfile/' + uid).map(user => User.fromJson(user));

}

logout() {

this.userInfo$.next(AuthService.EMPTY_USER);
this.authInfo$.next(AuthService.UNKNOWN_USER);
this.auth.logout();
}

更大的问题是,我应该使用行为主题跨应用程序共享数据吗? 或者我应该使用像用户$ = findUserByuid(uid)这样的observable,并将user $作为AuthService成员变量。 然后其他组件只订阅用户$?

我对在Angular2上共享数据的最佳方法感到困惑,没有使用类似于旧方式Angular 1的虚拟服务。我看到ppl使用Behavior Subject分享auth状态 - 这就是为什么我有所有这些问题和实现。 任何帮助将不胜感激! 关于行为主题没有太多资源。

[UPDATE]:我选择行为主题的原因而不仅仅是observable在我的应用程序的不同部分之间传递数据: 行为主题VS常规Observable

这是我写它的方式:

...

authInfo$: Observable<AuthInfo>;
userInfo$: Observable<User>;

constructor(private auth: FirebaseAuth, private db:AngularFireDatabase, @Inject(FirebaseRef) fb) {
  //firebase way to see if user is login or not
  this.authInfo$ = auth
    .startWith(null) // in case auth has no initial value
    .map(user => user ? new AuthInfo(user.uid) : AuthService.UNKNOWN_USER)
    .publishReplay(1)
    .refCount();

  // automatically update the unserInfo$ when authInfo$ changes (no matter from where)
  // ...we are "reacting" on the data emitted by authInfo$ ... hence the name "reactive" programming
  this.userInfo$ = this.authInfo$
    .switchMap(authInfo => this.findUserByuid(authInfo.uid))
    .publishReplay(1);

  // this activates the whole stream-flow
  this.userInfo$.connect(); // instead of .connect() you could also append a ".refCount()" after the ".publishReplay(1)", however then it would only be acitve when there is at least 1 subscriber, so it depends on what you want
}

findUserByuid(uid?: string): Observable<User> {
  if (uid == null) {
    return Observable.of(AuthService.EMPTY_USER);
  } else {
    return this.db.object('userProfile/' + uid)
      .map(user => User.fromJson(user));
  }
}

logout() {
  this.auth.logout();
}

...

在我看来,两个在应用程序中共享数据的最佳方式是使用redux模式,在角度2中,它使用ngrx / store加上ngrx / effects实现。 以及智能组件和演示组件模式。

我有这些模式的例子

https://github.com/vigohe/ionic2-marvelApp

我的运行示例:

https://enigmatic-plains-75996.herokuapp.com/

来自ngrx repo的官方示例:

https://github.com/ngrx/example-app

更多信息:

尝试学习它,因为它会改变你的生活;)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM