我一直在使用带有firebase(angularfire2)的angular2创建一个Web应用程序, 我想知道我的开发方法是否已经过优化。
当用户选择一个组时,我会检查他是否已经是该组的成员。
ngOnInit() {
this.af.auth.subscribe(auth => {
if(auth) {
this.userConnected = auth;
}
});
this.router.params.subscribe(params=>{
this.idgroup=params['idgroup'];
});
this._groupService.getGroupById(this.idgroup).subscribe(
(group)=>{
this.group=group;
this.AlreadyPaticipe(this.group.id,this.userConnected.uid),
}
);
}
这个方法很有效,但是当我将函数AlreadyPaticipe(this.group.id,this.userConnected.uid)
放在getGroupById(this.idgroup).subscribe()
之外时,我得到一个错误组是未定的,我现在因为angular是异步的。我不知道我怎么能这样做?我如何优化代码?,如何将函数AlreadyPaticipe(this.group.id,this.userConnected.uid)
置于getGroupById(this.idgroup).subscribe()
提前致谢。
答案 0 :(得分:0)
首先,您不应该订阅那么多,最好的做法是将您的observable合并为一个并只订阅一次,因为每次订阅时,都需要在组件被销毁时进行清理(不适用于http,虽然不是ActivatedRoute),但你最终还是必须管理你的订阅(这不是RXjs的目标)。您可以找到a good article on this topic here。
您必须将所有内容都视为流,所有属性都是可观察的:
this.user$ = this.af.auth.share(); //not sure of the share, I don't know firebase, don't know what it implies...
this.group$ = this.router.params.map(params => params["idgroup"])
.switchMap(groupID => this.groupService.getGroupById(groupID)).share();
// I imagine that AlreadyPaticipe return true or false, but maybe i'm wrong
this.isMemberOfGroup$ = Observable.combineLatest(
this.group$,
this.user$.filter(user => user !== null)
).flatMap(([group, user]) => this.AlreadyPaticipe(groupID, user.uid));
您甚至不必订阅!在您的模板中,您只需使用async
管道。例如:
<span>user: {{user$|async}}</span>
<span>group : {{group$|async}}</span>
<span>member of group : {{isMemberOfGroup$|async}}</span>
或者如果您不想使用管道,您可以将所有可观察的和仅订阅组合一次:
this.subscription = Observable.combineLatest(
this.group$,
this.user$,
this.isMemberOfGroup$
).do(([group, user, memberofGroup]) => {
this.group = group;
this.user = user;
this.isMemberofGroup = memberofGroup;
}).subscribe()
在这种情况下,请不要忘记this.subscription.unsubscribe()
ngOnDestroy()
rxJS docs(位于页面底部)有一个非常方便的工具,可以帮助您选择合适的操作符来实现正确的行为。
如果您不想过多地更改代码,可以使用Resolve防护,它将在加载组件之前获取数据。 Take a look at the docs:
总之,您希望延迟渲染路由组件,直到获取所有必需的数据。 你需要一个解析器。