可观察数据服务,订阅不调用
Observable data service, subscribe not called
我想为用户对象创建一个响应式存储。因此,让我首先描述一下我尝试过的内容。我定义了一个简单的用户 class:
export class User {
constructor(public $key: string) {}
}
为简单起见,class 只包含一个密钥。我使用 firebase 存储并查询此存储我创建了一个服务 class:
export class UserService {
constructor(private af: AngularFire, private authService: AuthService) {}
getUser() {
return this.authService.authInfo$.concatMap(a => this.af.database.object('/users/' + a.uid));
}
}
getUser()
首先获取用户 ID 并查询特定用户的 firebase 数据库。但是我不想直接使用该服务。相反,我希望有一个具有 BehaviorSubject 的全局存储,其中包含最新的用户对象。那么让我们介绍一下商店:
export class UserStore {
private _user: BehaviorSubject<User> = new BehaviorSubject(null);
constructor(private userService: UserService) {
this.userService.getUser().subscribe(
userJson => {
this._user.next(new User(userJson.$key, userJson.firstName, userJson.lastName, null, userJson.personalDataSheet));
},
err => console.error
);
}
get user() {
return this._user.asObservable();
}
}
现在我在这样的组件中使用这个商店:
this.userStore.user.subscribe(
user => console.log(user)
);
而且有效!用户已登录。但是当我做类似
的事情时
user: User;
...
this.userStore.user.subscribe(
user => this.user = user
);
subscribe 只会在用户为空的情况下被调用一次。这是为什么? this.user = user
是否创建了另一种订阅并取消了第一个订阅?
问题是 至少有两个不同的值 被你的 BehaviorSubject 发出:
null
— 您在实例化主题时提供的初始值。
User
实例——当 Firebase 调用 returns. 时发出的值
- [可选] 修改后的
User
实例 — 由于 Firebase 的一切都是 "live",您的主题可能会继续为当前用户发出不同的实例(例如,您将获得一个新值如果用户注销)。
因此,根据 .subscribe()
的执行点,您最终可能会得到 null
值。
我会尝试改用 ReplaySubject。 ReplaySubject 只有在明确将值推入其中后才开始发射。这意味着您可以摆脱初始 null
值,只要 Firebase 没有返回,用户就不会可用(= 订阅将是 "waiting")。
更具体地说,这是我要更改的行:
private _user: ReplaySubject<User> = new ReplaySubject<User>(1);
我想为用户对象创建一个响应式存储。因此,让我首先描述一下我尝试过的内容。我定义了一个简单的用户 class:
export class User {
constructor(public $key: string) {}
}
为简单起见,class 只包含一个密钥。我使用 firebase 存储并查询此存储我创建了一个服务 class:
export class UserService {
constructor(private af: AngularFire, private authService: AuthService) {}
getUser() {
return this.authService.authInfo$.concatMap(a => this.af.database.object('/users/' + a.uid));
}
}
getUser()
首先获取用户 ID 并查询特定用户的 firebase 数据库。但是我不想直接使用该服务。相反,我希望有一个具有 BehaviorSubject 的全局存储,其中包含最新的用户对象。那么让我们介绍一下商店:
export class UserStore {
private _user: BehaviorSubject<User> = new BehaviorSubject(null);
constructor(private userService: UserService) {
this.userService.getUser().subscribe(
userJson => {
this._user.next(new User(userJson.$key, userJson.firstName, userJson.lastName, null, userJson.personalDataSheet));
},
err => console.error
);
}
get user() {
return this._user.asObservable();
}
}
现在我在这样的组件中使用这个商店:
this.userStore.user.subscribe(
user => console.log(user)
);
而且有效!用户已登录。但是当我做类似
的事情时user: User;
...
this.userStore.user.subscribe(
user => this.user = user
);
subscribe 只会在用户为空的情况下被调用一次。这是为什么? this.user = user
是否创建了另一种订阅并取消了第一个订阅?
问题是 至少有两个不同的值 被你的 BehaviorSubject 发出:
null
— 您在实例化主题时提供的初始值。User
实例——当 Firebase 调用 returns. 时发出的值
- [可选] 修改后的
User
实例 — 由于 Firebase 的一切都是 "live",您的主题可能会继续为当前用户发出不同的实例(例如,您将获得一个新值如果用户注销)。
因此,根据 .subscribe()
的执行点,您最终可能会得到 null
值。
我会尝试改用 ReplaySubject。 ReplaySubject 只有在明确将值推入其中后才开始发射。这意味着您可以摆脱初始 null
值,只要 Firebase 没有返回,用户就不会可用(= 订阅将是 "waiting")。
更具体地说,这是我要更改的行:
private _user: ReplaySubject<User> = new ReplaySubject<User>(1);