我在我的应用中将Firebase身份验证与Firestore(https://github.com/angular/angularfire2)一起使用。根据我当前的Firestore规则,我确保在退出之前取消订阅从Firestore检索到的所有可观察到的内容。但是,我收到“ FirebaseError:缺少或权限不足”。错误,我可以追溯到我在订阅中订阅的嵌套订阅,如下面的代码所示。
在ngOnDestory内部,我同时取消了两个订阅,但是仍然收到上一个错误。
this.proposalSubscription = this._posts.retrieveProposals(user.uid)
.subscribe(proposals => {
this.proposals = proposals;
this.proposals.forEach(proposal => {
this.chatSubscription = this._chat.retrieveChat(proposal.id).subscribe(chat => {
if (chat) {
this.chats.set(proposal.id, chat)
}
});
})
});
我几乎可以确定问题出在以下一行:this.chatSubscription = this._chat.retrieveChat(proposal.id).subscribe(chat => ...
即使我在退出前同时取消了proposalSubscription和chatSubscription,也仍然会收到错误消息。关于如何解决此问题的任何想法?另外,我对rxjs和运算符没有太多经验。有没有可以用来避免这种嵌套订阅的运算符?
谢谢。
答案 0 :(得分:2)
您可以这样设置订阅:
this.proposalSubscription = this._posts.retrieveProposals(user.uid)
.pipe(
switchMap(proposals => {
//if you need to save it in class variable you can save it like this
this.proposals = proposals;
const obs$ = proposals.map(p => {
return this._chat.retrieveChat(p.id)
.pipe(
map(chat => {
this.chats.set(p,id, chat);
})
)
});
return forkJoin(obs$);
})
)
.subscribe();
您可以根据需要组成运营商链,并且只有一个订阅。
在ngOnDestory
中取消订阅,如下所示:
ngOnDestroy() {
if(this.proposalSubscription) {
this.proposalSubscription.unsubscribe()
}
}
如果希望评估unsubscribe
仅可观察一次,则可以避免使用ngOnDestroy
在Subscription
中显式take(1)
并维护this._posts.retrieveProposals(user.uid)
实例像这样:
this._posts.retrieveProposals(user.uid)
.pipe(
take(1),
switchMap(proposals => {
//if you need to save it in class variable you can save it like this
this.proposals = proposals;
const obs$ = proposals.map(p => {
return this._chat.retrieveChat(p.id)
.pipe(
map(chat => {
this.chats.set(p,id, chat);
})
)
});
return forkJoin(obs$);
}),
)
.subscribe();
答案 1 :(得分:1)
嵌套订阅并不是处理相关可观察变量的最佳方法,我们通常使用switchMap。在同一组件中管理多个订阅的最佳方法是使用takeUntil,因为您可以将值发送到单个主题中,并一次性取消所有订阅。我们可以将提议映射到一个可观察对象数组,并使用CombineLatest返回这些可观察对象的结果数组。
finalise = new Subject();
this._posts.retrieveProposals(user.uid)
.pipe(
switchMap(proposals => combineLatest(proposals.map(proposal => this._chat.retrieveChat(proposal.id)))),
takeUntil(finalise)
).subscribe(chats => {
const chat = proposals.find(p => p);
this.chats.set(proposal.id, chat)
});
和ngOnDestroy
this.finalise.next();
所有观看的订阅都将在takeUntil中结束。