Angular和RxJS中的内存管理(泄漏?)

时间:2018-06-13 08:52:38

标签: angular memory memory-leaks rxjs

我试图在RxJS中推断用户的生命周期。也就是说,我们都知道我们需要取消订阅一个可观察的对吧?但问题是:为什么?

我正在开发一个基于Angular的大型应用程序,所以我无法真正分享我的代码,但我会尝试为您提供思考实验的背景。让我们说我们有以下组件:

class Comp extends Component {
    public o$;
    constructor(private store$: Store) {}
    ngOnInit() {
        this.o$ = this.store$.pipe(select(...), map(...));
        this.o$.subscribe(function() {
            this.whateverFromComponent(); // Let's tie this to component via closure
        });
    }
}

所以我们可以写一些类似this.o$.pipe(takeUntil(this.onDestroy$))但我使用原生角色路由器的东西,所以当我更改子页面时,Comp类实例被删除,并且唯一引用{ {1}}被移除,因此删除了对回调的唯一引用,我们全部完成了吗?

但情况似乎并非如此:当从DOM中删除组件并调用o$时,我预计onDestroy的实例也会被删除,但它会#39 ; s显然没有删除,否则我们不需要取消订阅可观察资料。

所以我开始认为,Angular会创建一次组件的实例,并且当它未被使用时,不会删除对组件类实例的引用,而是保留以供进一步使用。但似乎并非如此,因为每次在页面上呈现组件时都会调用放入构造函数的comp

好的,所以在这一点上我知道组件实例在从DOM中删除时不会从内存中删除,因为无论如何都会调用订阅。每次将组件实例放入DOM时,都会创建组件实例。 Waaaat?

我已经运行DevTools并获取内存快照并过滤了我的组件类名称。事实上,似乎每次组件都在页面上呈现,就会创建一个新实例。因此,即使只需要一个组件,我也会得到n个参考组件。

我开始挖掘并从一些订阅中引用过时的组件实例,这似乎来自Angular Router。

你能否帮我弄清楚何时(如果有的话)是从内存中删除的Component类的实例?为什么订阅仍然存在?

1 个答案:

答案 0 :(得分:1)

只要流处于活动状态,它显然需要对所有订阅的引用。否则它无法向订阅者发出值。但是,当流完成时,情况就不再如此。

在您的示例store$中(很可能)永远不会完成,因此您需要取消订阅。否则,订阅以及流将保持活动状态(尽管名称store$意味着此特定流可能与应用程序一样长。)

从内存中删除组件实例时,取决于垃圾收集器以及某些代码是否仍保留对该实例的引用。