2017-10-02 2 views
1

Ich versuche, einen Benutzerprofil-Service für ein Angular 4-Projekt zu erstellen, und kämpfe ein wenig damit, wie man das beobachtbare Profile-Objekt richtig initialisiert und aktualisiert. Wenn sich der Benutzer derzeit (über Firebase) authentifiziert, übergibt AuthService die Authentifizierungsinformationen des Benutzers an UserProfileService über dessen Funktion initialize(). UserProfileService sucht dann das Benutzerprofil (oder erstellt ein Profil, wenn noch keines vorhanden ist) und füllt eine öffentliche Observable mit dem Profil auf.Eine Observable abonnieren, bevor sie ausgefüllt wurde

Das Problem, das ich renne, ist mit anderen Teilen der Anwendung, die versucht, das beobachtbare Profil zu abonnieren, bevor all das passiert ist. Ich hatte ursprünglich die Initialisierung der beobachtbare über ...

public profileObservable: UserProfile = null; 

... was natürlich in einer Folge „subscribe() existiert nicht auf null“ Fehler, also habe ich es zu ...

Dies zumindest wirft keine Fehler, aber alles, das profileObservable abonniert, bevor ich das Firebase-Objekt zugeordnet habe, wird nie aktualisiert.

Kompletter Code für user-profile.service.ts unten. Ich ringe immer noch darum herumzukommen, wie das funktionieren soll, hoffentlich kann jemand etwas Licht geben. Vielen Dank!

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)); 
    } 
}; 

Antwort

3

Sie dürfen beobachtbare Referenzen nicht ändern, nachdem Sie sie erstellt haben. Die Art, wie ich Abonnenten von der Datenquelle richtig entkoppeln kann, besteht darin, ein Zwischenprodukt Subject zu verwenden, das sowohl ein Beobachter als auch ein Observable ist.

Ihr Code würde wie folgt aussehen:

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

Sie werden wahrscheinlich mehr Glück mit 'neuer ReplaySubject (1)' so dass spät Abonnent noch das letzte Benutzerprofil zur Verfügung gestellt erhalten können. – Brandon

Verwandte Themen