我想订阅一个observable的时间只有一个emit触发其他事件。例如,订阅路由中的查询参数,以便从发射器触发另一个事件 - 其中发出的值不是。其实很重要。或者,例如,如果我有一个BehaviorSubject并且需要根据对该主题的更改重新加载某些组件。在这些情况下,可观察量并不意味着被模板使用,并且它们发出的值在很大程度上被忽视。
理想情况下,我会写一些类似的东西:
ngOnInit() {
this.service.behaviorSubject.subscribe(
() => callLocalMethod()
)
}
问题在于,一旦组件被销毁,angular就不会取消订阅该订阅,这意味着每次组件被初始化和销毁时,除了旧订阅之外还会创建新订阅并从可观察者发出新订阅。要求每个冗余订阅。由于订阅未分配给属性,因此无法取消订阅OnDestroy生命周期钩子(我可以告诉) - 但是对于此用例来说,将其分配给属性似乎是不必要的。
所以我最终要做的是为每个订阅创建一个属性,即使该属性永远不会被使用,将其分配给订阅,然后在组件为时调用unsubscribe()
销毁。
这似乎是多余的 - 有更好的方法吗?使用异步管道处理订阅不是一个选项,而使用EventEmitter也不是一个选项,因为通常希望它的行为类似于热的可观察性。
答案 0 :(得分:5)
您可以使用其他主题:
private destroy$ = new Subject();
constructor() {
obs$
// Ensures that we complete when the component is
// destroyed. Completing will automatically unsubscribe.
.takeUntil(this.destroy$)
.subscribe();
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
关于这一点的好处是,它可以很好地扩展,因为无论您管理的订阅数量多少,都只需要一次样板文件。
另请注意,当组件被销毁时,ActivatedRouter实际上会完成params
/ paramMap
,因此无需手动取消订阅参数更改。
答案 1 :(得分:3)
使用takeWhile你可以简单地使用布尔变量
private alive: boolean = true; //we use a variable
//All ours subscriptions are like
this.service.method()
.takeWhile(() => this.alive)
.subscribe(result => {...})
//in ngOnDestroy
public ngOnDestroy() {
this.alive = false;
}