是否有一个确认和优雅的成语取消订阅控制器中所有现有但可能未初始化的订阅?请考虑以下代码段:
/* Somewhere on init */
if(/* condition 1 */) {
this.subscription1 = this.service1().subscribe();
}
if(/* condition 2 */) {
this.subscription2 = this.service2().subscribe();
}
在清理阶段:
onDestory() {
try{
this.subscription1.unsubscribe();
this.subscription2.unsubscribe();
} catch e {
/* One of subscriptions was uninitialized */
/* If that was first one, second may be left unsubscribed */
}
}
基本上有一些直截了当的方法,如心爱的ifology:
if(this.subscription1) {
this.subscription1.unsubscribe();
}
if(this.subscription2) {
this.subscription2.unsubscribe();
}
使用订阅数组而不是控制器字段:
/* Somewhere on init */
if(/* condition 1 */) {
this.subscriptions.push(this.service1().subscribe())
}
if(/* condition 2 */) {
this.subscriptions.push(this.service2().subscribe())
}
noDestroy() {
this.subscriptions.forEach(s => s.unsubscribe();)
}
但也许有一些干净可靠的方法来完成这样的任务?根据我的经验,如果您希望在onDestroy
以外的其他控制器生命周期中有选择地取消订阅所选订阅,则基于数组的基于数组会使您的订阅列表无法处理,因此基于数组而言很容易保存并且很容易忘记更新。
为什么不使用takeUntil
RxJs运算符?
你可以订阅你想要的observable,当另一个Observable发出时,等待takeUntil运算符取消订阅Observable链:
您可以将新的Observable声明为主题:
private destroySubscriptions$ = new Subject<void>();
/* Somewhere on init */
if(/* condition 1 */) {
this.service1()
.pipe(
takeUntil(this.destroySubscriptions$)
).subscribe();
}
if(/* condition 2 */) {
this.service2()
.pipe(
takeUntil(this.destroySubscriptions$)
).subscribe();
}
在清理阶段(通常在onDestroy
Angular生命周期钩子上):
ngOnDestroy() {
this.destroySubscriptions$.next();
}
此外,这是RxJs中的推荐模式,以摧毁您的订阅!您可以阅读有关takeUntil
运算符here的更多信息。
你可以使用takeUntil:
import { OnDestroy, OnInit } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
export class MyComponent implements OnInit, OnDestroy {
private readonly ngUnSub: Subject<void>;
constructor() {
this.ngUnSub = new Subject<void>();
}
public ngOnInit(): void {
if (condition1) {
this.service1.pipe(takeUntil(this.ngUnSub)).subscribe();
}
if (condition2) {
this.service2.pipe(takeUntil(this.ngUnSub)).subscribe();
}
}
public ngOnDestroy(): void {
this.ngUnSub.next();
this.ngUnSub.complete();
}
你可以这样做:
import { Subscription } from 'rxjs';
...
export class MyComponent implements OnInit, OnDestroy {
private subscriptions: Subscription[] = [];
...
ngOnDestroy() {
this.subscriptions.forEach(sub => sub.unsubscribe());
}
....
if(/* condition 1 */) {
this.subscriptions.push(this.service1().subscribe());
}
if(/* condition 2 */) {
this.subscriptions.push(this.service2().subscribe());
}
}