[英]Subscribing to an observable before it's been populated
我正在嘗試為Angular 4項目創建用戶配置文件服務,並且在如何正確初始化和更新可觀察的Profile對象方面有些掙扎。 當前,當用戶通過Firebase進行身份驗證時,AuthService會通過后者的initialize()函數將用戶的身份驗證信息傳遞給UserProfileService。 然后,UserProfileService查找用戶的個人資料(如果不存在,則創建一個),並使用該個人資料填充可觀察的公共對象。
我遇到的問題是應用程序的其他部分試圖在所有這些事情發生之前訂閱可觀察的配置文件。 我本來是通過...初始化可觀察的
public profileObservable: UserProfile = null;
...當然會導致“ subscribe()不存在為空”錯誤,因此我將其更改為...
public profileObservable: Observable<UserProfile> = Observable.of();
這至少不會引發任何錯誤,但是在將Firebase對象映射到profileObservable之前,任何訂閱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));
}
};
構造可觀察參考之后,就不得更改它們。 我發現正確地將訂閱者與數據源分離的方法是使用中間的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);
}
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.