Angular 4 & RxJS:竞争条件、服务初始化顺序和就绪

Angular 4 & RxJS: race conditions, service initialisation order and readiness

我想确认我对可观察对象与服务初始化的使用是正确的,还是没有被标准模式打败。我是可观察对象的新手。

假设我有多个服务(例如 profileService),具体取决于 authService 的准备情况:一些数据只应在用户已知后加载。

authentication service 发出 (observer.next('userConnected')) 用户成功通过应用程序身份验证的信号时,示例 profileService 应该只 "obtain the connected user's profile"。

我的profileService看起来如下:

constructor(@Inject(AuthenticationService) private authSvc: AuthenticationService){
        this.authSvc.getAuthChangeObservable().subscribe(data => this.onAuthenticationChanged(data) );
  }

authenticationService的写法如下:

private authChange: Observable<any>;
private _authObserver: Observer<any>;

constructor(@Inject(FirebaseService) firebaseService: FirebaseService){

    // Cookies or whatever allow .auth() to identify the user after a page refresh
    // This causes a slight delay, see my question below
    firebase.auth().onAuthStateChanged(user => {
      if(user) this.onAuthenticationSuccessfull(user);
      else this.onLogoutSuccessfull();
    });

    // Create an observable for auth status
    this.authChange = new Observable(observer => {
      this._authObserver = observer;
    }).share();
  }

  getAuthChangeObservable(){
    return this.authChange;
  }

...

onAuthenticationSuccessfull(user){
    this.authenticatedUser = user;

    // This is mainly the way I found to warn other services they are clear to load the
    // user-related data
    this._authObserver.next('auth');
}
...

困扰我的是:如果身份验证没有延迟怎么办?或者在更通用的服务的情况下,如何确保依赖于它的所有服务都已准备好并订阅了 observable?

我知道 observable.share() 存在竞争条件。除非错误,只要至少调用一次 share() ,就会触发第一个 "pending" 事件。我需要调用 .share() 因为我需要一个 "hot" 可观察对象(即不重新 运行 可观察对象的观察者 .next() 例程)。

提前感谢您分享建议和技巧。

您可以使用 Subject 来简化代码,它是一个热观察对象,默认情况下它不会缓存过去的事件(您描述的共享行为更像是 BehaviorSubject)

在您的身份验证服务中

public onAuth=new Subject()
constructor(@Inject(FirebaseService) firebaseService: FirebaseService){

firebase.auth().onAuthStateChanged(user => {
  if(user) this.onAuth.next(user);
  else this.onLogoutSuccessfull();
})

在您的个人资料服务中

constructor(@Inject(AuthenticationService) private authSvc: 
AuthenticationService){
// onlogin
    this.authSvc.onAuth.filter(user=>user&&user.id).map(data=>
// you can perform other operation here e.g chain, combine 
).subscribe()

// onlogout
    this.authSvc.onAuth.filter(user=>!user).map(data=>
// you can perform other operation here e.g chain, combine 
).subscribe()

}