javascript - 如果 Observable 完成,我是否需要取消订阅 Observable?

标签 javascript memory-leaks rxjs

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

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 方法?

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 现在都符合垃圾收集的条件,并且将被销毁,即使它们引用了每个其他。还是有一些我不知道的隐藏引用?

不要担心使用unsubscribetakeUntil 或其他机制之间的区别。

最佳答案

如果是 let subject$ = new Subject();清除对 Subject 的引用和 Subscription就足够了,之后一切都会被垃圾收集。

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

让我们举个例子:

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 有引用的回调, 使其整体无法收藏。

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

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

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

作为结论,只要一个Observable被销毁时,这些并没有真正的内存泄漏风险,因为所有订阅也将被销毁。冒险Observables那些是永久性的(例如:附加到带有 fromEvent 的全局 DOM 事件),并且回调指向需要销毁的对象。

关于javascript - 如果 Observable 完成,我是否需要取消订阅 Observable?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59653696/

相关文章:

javascript - 使用 for 循环语法创建函数

memory-leaks - IE 6 中存在内存泄漏的大型 Web 应用程序

angular - 一般如何链接对 ng2-Translate 和 rxjs 可观察量的调用?

Angular 6 : Error handling with forkJoin

node.js - 如何用观察者替换订阅者?

JavaScript 闭包和范围问题

javascript - 如何将 $scope 传递给 angularjs 1.5 组件/指令

javascript - TypeScript 包创建声明文件

iphone - 无法修复 Open AL 中的严重内存泄漏

c - 内存破坏错误