使用takeUntil模式退订Observable时是否需要完成Subject?

时间:2019-02-02 10:12:23

标签: javascript angular rxjs

为了避免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()有什么后果?

2 个答案:

答案 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(),就不会破坏任何东西。

相关问题