Angular 2 / Rxjs:我真的需要取消订阅吗?

10

我明白当组件销毁时,我必须取消订阅某些Observable(例如:具有无限值的Observables),以防止内存泄漏。对于有限的Observables,我不需要这样做,因为它们将会自动完成并自动unsubscribe

但是,如果我在组件中创建一个Observable(例如FormGroup.valueChangesQueryList.changes)并且它是无限的,那么它将随包含它的组件一起被销毁,所以我认为即使我没有取消订阅它,也不会出现内存泄漏。

这里是一个简单的例子:

@Component({})
export class DummyComponent {
    form: FormGroup;

    constructor(private fb: FormBuilder) {
        this.form = this.fb.group({
            firstName: [''],
            lastName: ['']
        });
        this.form.valueChanges.subscribe(
            x => console.log(x)
        );
    }
}

在这里,我不会从this.form.valueChangesunsubscribe;当我的组件被销毁时,this.form.valueChanges也将被销毁。

在这种情况下会出现内存泄漏吗?


3
你尝试过在subscribe(...)中添加一个完整的回调函数并检查当组件被销毁时是否会调用它吗? - Günter Zöchbauer
我已经这样做了,但它没有被调用(我只是使用 this.form.valueChanges 进行了测试)。 - petitcl
我想那么做会更好,但不一定需要取消订阅。我不会期望有内存泄漏,因为当组件被销毁时,它将被垃圾回收,并随之取消订阅。如果您在组件外部(例如服务)订阅或传递订阅,则可能会防止组件被垃圾回收,但如果所有内容都在组件内部,那么不应该有影响。 - Günter Zöchbauer
2个回答

8
正如Babar所提到的那样,您需要取消订阅以停止这些订阅继续观察变化。

针对您特定的情况,我认为您是有道理的。

当我在同一组件中有很多订阅时,我会做以下操作。

首先创建“subscriptions”,一个Subscription类型的空数组。

private subscriptions: Subscription[] = [];

然后每次我需要订阅时,就将其推入数组中。

this.subscriptions.push(this.form.valueChanges.subscribe(x => console.log(x)));

在 ngOnDestroy 中,我取消订阅数组中的每个订阅。
ngOnDestroy(): void {
  this.subscriptions.forEach((elem) => { elem.unsubscribe(); })
}

3
您可以使用subscription.add()方法将订阅项相互添加。然后只需取消顶部的订阅即可。 - DarkNeuron

3
当您的组件被销毁时,您的订阅者并不会被销毁,它们仍在等待任何事件的到来,这将导致内存消耗增加,有时还会干扰您的逻辑。例如,路由器事件订阅将在应用程序中触发,并执行您在订阅中编写的代码。
第二种情况是,如果您在组件之间切换并且从未取消订阅,则在一段时间后,您的应用程序将挂起,因为每当加载新组件时都会绑定新的订阅者。
@Component({})
export class DummyComponent implements OnDestroy {
 form: FormGroup;
 subscription: Subscription; // from rxjs
 constructor(private fb: FormBuilder) {
    this.form = this.fb.group({
        firstName: [''],
        lastName: ['']
    });
    this.subscription = this.form.valueChanges.subscribe(
        x => console.log(x)
    );
 }

 ngOnDestroy(): void {
  this.subscription.unsubscribe();
 }
}

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