RXJS - Angular - 取消订阅主题
RXJS - Angular - unsubscribe from Subjects
如所述,'official'取消订阅Observables的解决方案Angular 5+通常使用takeUntil。到目前为止,一切都很好。我的问题是,如果我订阅的 Observable 实际上是一个 Subject,这是否也适用?
一旦你调用 .subscribe()
任何东西(也包括主题),需要一些东西来确保订阅被取消订阅。
处理有限的 Observables:
如果你订阅了一个有限的可观察对象(意味着一个具有 finite/limited 序列的可观察对象),最后一条消息将发送一个结束信号并且订阅将自动取消。
这方面的例子是:
Observable.of(100)
Observable.from([1,2,3,4])
在有限观测值中的例子是:
Observable.fromEvent(document, 'click')
Observable.timer(1000)
Calling/piping .first()
、.take(number)
或 .takeWhile(condition that will evaluate to false at some point)
或 takeUntil(observable that emits a value)
上的可观察值都会将原本无限的可观察值变成有限的。
停止调用.subscribe():
不必取消订阅的另一种流行方法是首先不订阅。这听起来可能很愚蠢,因为你什么时候想要一个你不订阅的可观察对象?好吧,如果您只需要将一些数据传递给 view/html 模板,将可观察到的管道传递到异步管道中会将取消订阅问题传递给异步管道本身。
html模板中的典型示例:
<h1>Editing {{ infiniteObservable$ | async }}<h1>
<li *ngFor="let user of userObservable$ | async as users; index as i; first as isFirst">
{{i}}/{{users.length}}. {{user}} <span *ngIf="isFirst">default</span>
</li>
手动取消订阅:最后,您可以选择保留对所有订阅的引用。您不必保留指向每个订阅的变量,只使用一个订阅对象来跟踪所有订阅,然后一次取消订阅所有订阅会更容易。
这是一个例子:
const subscriptions = new Subscription();
subscriptions.add(observable1$.subscribe());
subscriptions.add(observable2$.subscribe());
subscriptions.unsubscribe();
快速总结,如何处理退订,以下方法之一:
- 将无限的可观察值变成有限的,因此无需取消订阅(使用
.takeUntil(this.destroyed$)
并在 ngOnDestroy()
中执行 this.destroyed$.emit()
)。
- 避免订阅,并通过
async
管道传递可观察对象。
- 保留对任何订阅的引用并在
ngOnDestroy()
方法中调用 .unsubscribe()
。
就我个人而言,我倾向于只使用前两种方法中的一种。
我有事要补充。 Subject
在内部存储订阅者(Observable
也是)。如果 Subject
是您的组件的一部分(在内部创建,存储为 属性 或在闭包中),主题及其订阅将与组件本身一起被垃圾收集。
但这是一种特殊情况,应该非常小心:所有内容都必须包含在组件中。
例如不 取消订阅 FormControl.valueChanges
可观察对象是安全的,如果它只在组件中使用的话。
不过保险起见,也不想多想,就用takeUntil
.
如
一旦你调用 .subscribe()
任何东西(也包括主题),需要一些东西来确保订阅被取消订阅。
处理有限的 Observables: 如果你订阅了一个有限的可观察对象(意味着一个具有 finite/limited 序列的可观察对象),最后一条消息将发送一个结束信号并且订阅将自动取消。 这方面的例子是:
Observable.of(100)
Observable.from([1,2,3,4])
在有限观测值中的例子是:
Observable.fromEvent(document, 'click')
Observable.timer(1000)
Calling/piping .first()
、.take(number)
或 .takeWhile(condition that will evaluate to false at some point)
或 takeUntil(observable that emits a value)
上的可观察值都会将原本无限的可观察值变成有限的。
停止调用.subscribe(): 不必取消订阅的另一种流行方法是首先不订阅。这听起来可能很愚蠢,因为你什么时候想要一个你不订阅的可观察对象?好吧,如果您只需要将一些数据传递给 view/html 模板,将可观察到的管道传递到异步管道中会将取消订阅问题传递给异步管道本身。
html模板中的典型示例:
<h1>Editing {{ infiniteObservable$ | async }}<h1>
<li *ngFor="let user of userObservable$ | async as users; index as i; first as isFirst">
{{i}}/{{users.length}}. {{user}} <span *ngIf="isFirst">default</span>
</li>
手动取消订阅:最后,您可以选择保留对所有订阅的引用。您不必保留指向每个订阅的变量,只使用一个订阅对象来跟踪所有订阅,然后一次取消订阅所有订阅会更容易。 这是一个例子:
const subscriptions = new Subscription();
subscriptions.add(observable1$.subscribe());
subscriptions.add(observable2$.subscribe());
subscriptions.unsubscribe();
快速总结,如何处理退订,以下方法之一:
- 将无限的可观察值变成有限的,因此无需取消订阅(使用
.takeUntil(this.destroyed$)
并在ngOnDestroy()
中执行this.destroyed$.emit()
)。 - 避免订阅,并通过
async
管道传递可观察对象。 - 保留对任何订阅的引用并在
ngOnDestroy()
方法中调用.unsubscribe()
。
就我个人而言,我倾向于只使用前两种方法中的一种。
我有事要补充。 Subject
在内部存储订阅者(Observable
也是)。如果 Subject
是您的组件的一部分(在内部创建,存储为 属性 或在闭包中),主题及其订阅将与组件本身一起被垃圾收集。
但这是一种特殊情况,应该非常小心:所有内容都必须包含在组件中。
例如不 取消订阅 FormControl.valueChanges
可观察对象是安全的,如果它只在组件中使用的话。
不过保险起见,也不想多想,就用takeUntil
.