我是Observable样式编程的新手。我有一个问题:我希望在组件之间跨应用程序共享用户信息 - 我使用BehaviorSubject来共享此信息。这是通过将BehaviorSubject共享为AuthInfo来启发的。如果我可以在我的应用程序组件中共享包含uid的AuthInfo,为什么我可以使用它来共享我的用户对象数据?
问题是,用户对象,我是从Firebase获得的。所以它是一个Observable,我不知道如何将它分配给一个行为主题。所以这是我尝试的代码:
@Injectable()
export class AuthService {
static UNKNOWN_USER = new AuthInfo(null);
static EMPTY_USER = new User(null, null, null, null);
authInfo$: BehaviorSubject<AuthInfo> = new BehaviorSubject<AuthInfo>(AuthService.UNKNOWN_USER);
userInfo$: BehaviorSubject<User> = new BehaviorSubject<User>(AuthService.EMPTY_USER);
constructor(private auth: FirebaseAuth, private db:AngularFireDatabase, @Inject(FirebaseRef) fb) {
//firebase way to see if user is login or not
this.auth.subscribe(user => {
if (user) {
const authInfo = new AuthInfo(user.uid);
this.authInfo$.next(authInfo);
//This is the part I do not know how to do
[OPTION 1]: this.userInfo$.next(findUserByuid(user.uid)) ?? - error
[OPTION 2]: this.userInfo$ = findUserByuid(user.uid) ?? - userInfo$ turn into an observerable, which when I logout to call this.userInfo$.next(AuthService.EMPTY_USER) it will throw error as .next() is not a function.
[OPTION 3]:
this.findUserByuid(user.uid).subscribe(user => {
this.userInfo$.next(user);
});
---- Can I put a subscribe inside of another subscribe to chain it like promise? I am not sure this is following the best practices. But this is the only option that there is no error. But just not sure I am doing it right. I do get the user object no problem
}
else {
this.authInfo$.next(AuthService.UNKNOWN_USER);
}
});
}
findUserByuid(uid:string):any {
//return a firebase object observerable
return this.db.object('userProfile/' + uid).map(user => User.fromJson(user));
}
logout() {
this.userInfo$.next(AuthService.EMPTY_USER);
this.authInfo$.next(AuthService.UNKNOWN_USER);
this.auth.logout();
}
更大的问题是,我应该使用行为主题在应用程序之间共享数据吗?或者我应该使用像用户$ = findUserByuid(uid)这样的observable,并将user $作为AuthService成员变量。然后其他组件只订阅用户$?
我对在Angular2上共享数据的最佳方法感到困惑,没有使用类似于旧方式Angular 1的虚拟服务。我看到ppl使用Behavior Subject分享auth状态 - 这就是为什么我有所有这些问题和实现。任何帮助将不胜感激!关于行为主题没有太多资源。
[更新]:我选择行为主题的原因,而不仅仅是observable在我的应用程序的不同部分之间传递数据: Behavior Subject VS regular Observable
答案 0 :(得分:3)
这就是我写它的方式:
...
authInfo$: Observable<AuthInfo>;
userInfo$: Observable<User>;
constructor(private auth: FirebaseAuth, private db:AngularFireDatabase, @Inject(FirebaseRef) fb) {
//firebase way to see if user is login or not
this.authInfo$ = auth
.startWith(null) // in case auth has no initial value
.map(user => user ? new AuthInfo(user.uid) : AuthService.UNKNOWN_USER)
.publishReplay(1)
.refCount();
// automatically update the unserInfo$ when authInfo$ changes (no matter from where)
// ...we are "reacting" on the data emitted by authInfo$ ... hence the name "reactive" programming
this.userInfo$ = this.authInfo$
.switchMap(authInfo => this.findUserByuid(authInfo.uid))
.publishReplay(1);
// this activates the whole stream-flow
this.userInfo$.connect(); // instead of .connect() you could also append a ".refCount()" after the ".publishReplay(1)", however then it would only be acitve when there is at least 1 subscriber, so it depends on what you want
}
findUserByuid(uid?: string): Observable<User> {
if (uid == null) {
return Observable.of(AuthService.EMPTY_USER);
} else {
return this.db.object('userProfile/' + uid)
.map(user => User.fromJson(user));
}
}
logout() {
this.auth.logout();
}
...
答案 1 :(得分:2)
在我看来,两个人在应用程序中共享数据的最佳方式是使用在角度2中使用nxx / store加上ngrx / effects实现的redux模式。以及智能组件和表示组件模式。
我有一个关于这些模式的例子
https://github.com/vigohe/ionic2-marvelApp
我正在运行的例子:
https://enigmatic-plains-75996.herokuapp.com/
来自ngrx repo的官方示例:
https://github.com/ngrx/example-app
更多信息:
尝试学习它,因为它会改变你的生活;)