2017-10-02 10 views
1

私はAngular 4プロジェクト用のユーザープロファイルサービスを作成しようとしていますが、Observable Profileオブジェクトを適切に初期化して更新する方法について少し苦労しています。現在、ユーザーが(Firebaseを介して)認証すると、AuthServiceは、ユーザーのauth情報を、後者のinitialize()関数を介してUserProfileServiceに渡します。 UserProfileServiceはユーザーのプロファイルを検索し(まだ存在しない場合は作成します)、そのプロファイルでパブリックオブザーバブルを設定します。Observableがポピュレートされる前にobservableを購読する

私が遭遇している問題は、これが起こる前にプロファイル観測可能なアプリケーションを購読しようとしているアプリケーションの他の部分です。私はもともと、初期化されてのだ...経て、観察もちろん「ヌルに存在しない)(サブスクライブ」エラーになったので、私はそれを変更

public profileObservable: UserProfile = null; 

... ...

public profileObservable: Observable<UserProfile> = Observable.of(); 

これは少なくともエラーは発生しませんが、Firebaseオブジェクトをマップする前にprofileObservableにサブスクライブするものは更新されません。

下記のuser-profile.service.tsの完全なコード。私はまだいくつかのことが働くことを念頭に置いて頑張っています。誰かが光を放つことを願っています。ありがとう!

import { Injectable } from '@angular/core'; 
import { Observable } from 'rxjs/Observable'; 
import 'rxjs/add/observable/of'; 
import { FirebaseListObservable, FirebaseObjectObservable, AngularFireDatabase } from 'angularfire2/database'; 
import * as firebase from 'firebase/app'; 

export class UserProfile { 
    $exists: Function; 
    display_name: string; 
    created_at: Date; 
} 

@Injectable() 
export class UserProfileService { 
    private basePath: string = '/user-profiles'; 
    private profileRef: FirebaseObjectObservable<UserProfile>; 
    public profileObservable: Observable<UserProfile> = Observable.of(); 

    constructor(private db: AngularFireDatabase) { 
     // This subscription will never return anything 
     this.profileObservable.subscribe(x => console.log(x)); 
    } 

    initialize(auth) { 
     this.profileRef = this.db.object(`${this.basePath}/${auth.uid}`); 
     const subscription = this.profileRef.subscribe(profile => { 
      if (!profile.$exists()) { 
       this.profileRef.update({ 
        display_name: auth.displayName || auth.email, 
        created_at: new Date().toString(), 
       }); 
      } else subscription.unsubscribe(); 
     }); 

     this.profileObservable = this.profileRef.map(profile => profile); 

     // This subscription will return the profile once it's retrieved (and any updates) 
     this.profileObservable.subscribe(profile => console.log(profile)); 
    } 
}; 

答えて

3

観察可能な参照を変更してはなりません。私がデータソースから加入者を適切に切り離す方法は、オブザーバとオブザーバブルの両方である中間Subjectを使用することです。

あなたのコードは次のようになります:

import { Observable } from 'rxjs/Observable'; 
import { Subject } from 'rxjs/Subject'; 

... 

export class UserProfileService { 
    ... 
    public profileObservable = new Subject<UserProfile>(); 

    constructor(private db: AngularFireDatabase) { 
     // This subscription now works 
     this.profileObservable.subscribe(x => console.log(x)); 
    } 

    initialize(auth) { 
     const profileRef = this.db.object(`${this.basePath}/${auth.uid}`); 

     ... 

     profileRef.subscribe(this.profileObservable); 
    } 
}; 
+1

あなたはおそらく '新しいReplaySubject を使用して、より良い運を持っています(1)'後半加入者はまだ提供される最も最近のUSERPROFILEを受け取ることができるようになりますように。 – Brandon

関連する問題