Angular RxJS - 如何取消 mergeMap 的订阅?

3

遵循这篇Stack Overflow文章中描述的最佳实践:Angular RxJS When Should I Unsubscribe From Subscription,请考虑使用此Angular组件生命周期钩子:

private ngUnsubscribe: Subject<void> = new Subject();

ngOnInit() {
  this.fireAuth.authState
    .takeUntil(this.ngUnsubscribe)
    .mergeMap((user) => this.todoService.getUserTodos(user.uid))
    .takeUntil(this.ngUnsubscribe)
    .subscribe((todos) => this.userTodoArray = todos);
}

ngOnDestroy() {
  this.ngUnsubscribe.next();
  this.ngUnsubscribe.complete();
}

作为 authState()mergeMap() 都返回 Observables,我想我应该:

  1. 取消订阅它们两个(如上所示),或者
  2. 只调用一个 takeUntil() 操作符,要么是从外部 Observable authState() 调用,要么是从内部 Observable this.todoService.getUserTodos(user.uid) 调用。

哪种方法是正确的以确保所有 Observables 在组件销毁后都已取消订阅?


这是第二个:你只需要一个 takeUntil 操作符,而且删除哪一个都无所谓。 - cartant
感谢您的回复。有关为什么#2是正确的任何解释或参考资料吗? - Stan
无论你使用哪个,都会看到流完成并且可观察对象取消订阅。如果没有其他人提供详细的解释,我可能稍后会添加一个答案。 - cartant
好的,没问题。感谢你! - Stan
我回来回答这个问题,意识到我的评论是错误的。很可能删除哪一个是有影响的,因为它们的行为是不同的。 - cartant
1个回答

18

你不需要同时使用两个takeUntil操作符。只需要一个,但是根据你移除的是哪个操作符,行为会有所不同。

如果你只使用第一个takeUntil,像这样:


this.fireAuth.authState
  .takeUntil(this.ngUnsubscribe)
  .mergeMap((user) => this.todoService.getUserTodos(user.uid))
  .subscribe((todos) => this.userTodoArray = todos);
this.ngUnsubscribe发出一个next通知时,takeUntil将取消订阅this.fireAuth.authState来源并完成。根据Observable Contract所述,当一个可观察对象完成时,它的订阅者将接收到一个complete通知,并自动取消订阅。
然而,如果this.fireAuth.authState发出了一个next通知,并且由mergeMap返回的getUserTodos可观察对象尚未完成,则mergeMap实现将不会取消订阅getUserTodos可观察对象。如果getUserTodos可观察对象稍后发出next通知,则该通知将流经到subscribe
如果您仅使用第二个takeUntil,请按以下方式操作:
this.fireAuth.authState
  .mergeMap((user) => this.todoService.getUserTodos(user.uid))
  .takeUntil(this.ngUnsubscribe)
  .subscribe((todos) => this.userTodoArray = todos);
this.ngUnsubscribe发出next通知时,takeUntil将取消订阅mergeMap,从而取消订阅this.fireAuth.authState和任何返回的getUserTodos可观察对象。

因此,在this.ngUnsubscribe发出后,没有任何通知会流经subscribe。这可能是您要寻找的行为,因此应删除第一个takeUntil运算符。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接