本文介绍了如果 Observable 已完成,我是否需要取消订阅 Observable?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个 Observable(热门,未完成),并且我订阅了它.通常,当我完成 Subscription 时,我必须取消订阅以防止内存泄漏.

Let us say I have an Observable (hot, doesn't complete), and I subscribe to it. Ordinarily when I am finished with the Subscription I have to unsubscribe it to prevent memory leaks.

let subject$ = new Subject();

const sub = subject$.subscribe(...);
...
// Need to call sub.unsubscribe() when we are finished
sub.unsubscribe();
sub = null;

但是如果不是仅仅完成 Subscription 我也完成了 Observable (Subject) 并且我删除了所有对两者都需要调用 unsubscribe 方法吗?

But if instead of just being finished with the Subscription I am also finished with the Observable (Subject) and I remove all reference to both, do I need to call unsubscribe method?

let subject$ = new Subject();

const sub = subject$.subscribe(...);
...
sub = null;
subject$=null;
// Assume I have no other references to these
// Do I need to call sub.unsubscribe() in this case?

我的逻辑告诉我我没有,因为 SubjectSubscription 现在都有资格进行垃圾收集,并且会被销毁,即使它们引用每个其他.还是有一些我不知道的隐藏参考?

My logic is telling my I don't because both the Subject and the Subscription are now eligible for garbage collection, and will be destroyed, even though they reference each other. Or is there some hidden reference I don't know about?

不用担心使用unsubscribetakeUntil或其他机制的区别.

Don't worry about the difference between using unsubscribe, takeUntil or other mechanisms.

推荐答案

如果 let subject$ = new Subject(); 清除对 Subject 的引用> 和 Subscription 就足够了,之后所有东西都会被垃圾收集.

In the case of a let subject$ = new Subject(); clearing the references to the Subject and the Subscription will be enough, everything will be garbage collected after that.

当您订阅对象中的 Subject 并且在清除所有引用之前不取消订阅 Subject 时,内存泄漏的风险就会变得真实在对象上.在这种情况下,整个对象将保持活动状态并且不会被垃圾回收.

The risk of a memory leak gets real when you are subscribing to the Subject in an object, and you don't unsubscribe from the Subject before clearing all the references on the object. In that case, the whole object will remain active and won't be garbage collectable.

让我们以这个例子为例:

Let's take this example:

class BigClass {
    constructor(observable) {
        this.bigArray = new Array(9999999).fill(0);
        observable.subscribe(x => this.result = x);
    }
    //...
}

let subject = new rxjs.Subject();
let bigObject = new BigClass(subject);
let bigObject1 = new BigClass(subject);
let bigObject2 = new BigClass(subject);
let bigObject3 = new BigClass(subject);

bigObject = null;
bigObject1 = null;
bigObject2 = null;
bigObject3 = null;

在这个例子中,当清除所有对 bigObject 的引用时,subject 仍然有对 x => 的引用.this.result = x 回调,它在 bigObject 上有一个引用,使它作为一个整体无法收集.

In this example, when clearing all the references on bigObject, the subject still has a reference on the x => this.result = x callback which has a reference on bigObject, making it uncollectable as a whole.

通过取消订阅或清除subject,这将破坏保持bigObject 存活的引用链,并且它将有资格进行垃圾收集.

Either by unsubscribing, or clearing the subject, this will break the references chain that keeps bigObject alive, and it will be eligible for garbage collection.

要自己观察行为,可以复制这个文件的内容https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.3/rxjs.umd.min.js 在您的控制台中,然后复制粘贴示例代码.您会注意到任务管理器中的内存增加.在开发人员工具的内存"选项卡中创建堆转储时,您可以通过在搜索字段中键入 BigClass 来找到这 4 个对象.

To observe the behavior by yourself, you can copy the content of this file https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.3/rxjs.umd.min.js in your console, then copy paste the example code. You will notice a memory increase in the task manager. When creating a heap dump in the Memory tab in the developer tools, you'll be able to find the 4 objects by typing BigClass in the search field.

之后,在控制台中输入subject = null;,然后创建一个新的堆转储.您会注意到 4 个对象已经消失.

After that, type subject = null; in the console, then create a new heap dump. You'll notice that the 4 objects have disappeared.

总而言之,只要 Observable 被销毁,这些都没有真正的内存泄漏风险,因为所有订阅也将被销毁.有风险的 Observables 是永久性的(例如:通过 fromEvent 附加到全局 DOM 事件),并且回调指向需要销毁的对象.

As a conclusion, as long as an Observable is destroyed, these is no real risk of a memory leak because all of the subscriptions will also be destroyed. The risky Observables are those who are permanent (e.g: attached to a global DOM event with fromEvent), and with callbacks referring to objects that need to be destroyed.

这篇关于如果 Observable 已完成,我是否需要取消订阅 Observable?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-03 17:24