为了避免Angular应用程序中的内存泄漏,我使用以下众所周知的模式从Observables退订:
unsubscribe = new Subject();
ngOnInit() {
this.myService.getStuff()
.pipe(takeUntil(this.unsubscribe))
.subscribe(result => {
// processing the result
});
}
ngOnDestroy() {
this.unsubscribe.next();
}
这似乎工作正常,但是在某些示例中,我注意到complete()
除了Subject
之外还被调用next()
:
ngOnDestroy() {
this.unsubscribe.next();
this.unsubscribe.complete(); // like this
}
在这里需要致电complete()
吗?如果是这样,为什么?在这种情况下不调用complete()
有什么后果?
答案 0 :(得分:2)
让我们看看为什么需要先取消订阅。
非常简化:可观察的实例包含所有预订的数组,这意味着您在subscribe
中拥有的每个回调都将保留在此数组中。这对于Component来说是个坏消息,因为尽管从这些函数中引用了它,但无法对其进行垃圾回收。我谈论这些功能:
ngOnInit() {
this.myService.getStuff()
.subscribe(
result => null, // this function will be stored in Observable
error => null, // and this
() => null, // and even this
);
}
,它适用于每个subscribe
呼叫。
现在,您添加了一个管道.pipe(takeUntil(this.unsubscribe))
(或者您可以例如使用my small library,它的作用类似但更短)。实际上,您的Observable订阅了Subject的事件。并且,无论何时发出值,this.myService.getStuff()
返回的Observable都会自动完成。这意味着上述所有三个功能将从此Observable的subscriptions数组中删除,并且不再从那里引用您的组件。
问题解决了。
首先,您需要了解所有的why
。
我们终于到了您的问题
ngOnDestroy() {
this.unsubscribe.next();
this.unsubscribe.complete();
}
其中complete
是不必要的,但也不会造成伤害。因为该主题的唯一订阅者是您来自this.myService.getStuff()
的Observable(或来自同一组件的其他Observable)。这意味着此Subject将不引用任何内容(唯一的侦听器已删除,应该清除所有订阅的complete
已为空),只要只有component引用此Subject作为其属性,它们都将被垃圾收集器收集。
答案 1 :(得分:1)
这已经在前面讨论过了。这里Why a 'next' before 'complete' of Angular takeuntil ngUnsubscribe?
您基本上不必致电complete()
,因为next()
会处理该链,而takeUntil
会为您取消订阅this.unsubscribe
。只有当你有一些其他的逻辑绑this.unsubscribe
那么它可能需要调用complete()
无论如何,只要您拨打complete()
,就不会破坏任何东西。