有没有方法可以在没有分配的情况下取消订阅BehaviorSubject?

Nik*_*vic 2 rxjs behaviorsubject rxjs5 reactive angular

有时间我想订阅一个observable只有一个emit触发附加事件.例如,订阅路由中的查询参数,以便从emit触发另一个事件 - 其中发出的值实际上并不重要.或者,例如,如果我有一个BehaviorSubject并且需要根据对该主题的更改重新加载某些组件.在这些情况下,observable不应由模板使用,并且它们发出的值在很大程度上被忽略.

理想情况下,我会写一些类似于:

ngOnInit() {
    this.service.behaviorSubject.subscribe(
        () => callLocalMethod()
    )
}
Run Code Online (Sandbox Code Playgroud)

问题是,一旦组件被销毁,angular就不会取消订阅该订阅,这意味着每次组件被初始化和销毁​​时,除了旧订阅之外,还会创建一个新订阅,并从每个订阅中调用这些订阅.冗余订阅.由于订阅未分配给属性,因此无法取消订阅OnDestroy生命周期钩子(因为我可以告诉) - 但是对于此用例,将其分配给属性似乎是不必要的.

所以我最终要做的是为每个订阅创建一个属性,即使该属性永远不会被使用,将它分配给订阅,然后unsubscribe()在组件被销毁时调用它.

这似乎是多余的 - 有更好的方法吗?使用异步管道处理订阅不是一种选择,并且使用EventEmitter也不是一种选择,因为通常希望它的行为类似于热的可观察性.

Ing*_*ürk 7

你可以使用另一个主题:

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();
}
Run Code Online (Sandbox Code Playgroud)

关于这一点的好处是,它可以很好地扩展,因为无论您管理的订阅数量多少,都只需要一次样板文件.

另请注意,ActivatedRouter实际上是在组件被销毁时完成params/ paramMap,因此不需要手动取消订阅参数更改.


Eli*_*seo 6

使用 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;
  }
Run Code Online (Sandbox Code Playgroud)