在填充之前订阅可观察对象

时间:2017-10-02 16:11:41

标签: javascript angular rxjs angularfire2

我正在尝试为Angular 4项目创建一个用户配置文件服务,并且正在努力解决如何正确初始化和更新可观察的Profile对象。目前,当用户进行身份验证(通过Firebase)时,AuthService会通过后者的initialize()函数将用户的身份验证信息传递给UserProfileService。然后,UserProfileService查找用户的配置文件(如果尚不存在,则创建一个配置文件)并使用配置文件填充公共可观察对象。

我遇到的问题是应用程序的其他部分试图在所有这些事件发生之前订阅配置文件observable。我最初通过......初始化了observable。

public profileObservable: UserProfile = null;

...当然导致“subscribe()在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));
    }
};

1 个答案:

答案 0 :(得分: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);
    }
};
相关问题