【问题标题】:Destroyed component's properties are accessible via subscription - how?被破坏的组件的属性可以通过订阅访问 - 如何?
【发布时间】:2021-10-09 18:29:49
【问题描述】:

我有这个example stackblitz,我在其中为组件设置了一个“id”,您可以通过复选框创建和销毁该组件。每次创建组件的新实例时,都会给它一个递增的 id。 在每个组件中,都有一个 interval 控制台记录组件的 ID。我没有在销毁时取消订阅它。 正如预期的那样,组件被销毁后我继续看到日志。让我感到困惑的是,不知何故interval 仍然知道它来自哪个组件,并且在引用它的 id 时不会引发错误。如果组件被销毁,它的属性如何仍然可以访问?组件是否仍然存在,造成内存泄漏?

【问题讨论】:

  • 是的!这是内存泄漏。这就是为什么你应该总是取消订阅。您可以将其视为一项全局服务,其中订阅实际上存储在 observable 上,这意味着它的生命周期不取决于设置订阅的组件。..
  • 对,但在第 19 行尝试访问 this.id 时不应该抛出引用错误吗?因为即使订阅仍然存在,组件也不应该存在,因为它已被销毁。 this 将不再是组件。所以我想知道“被破坏”的组件是否真的仍然存在,导致内存泄漏。
  • 阅读“闭包”以更好地理解为什么会这样......

标签: angular rxjs angular-component-life-cycle


【解决方案1】:

在阅读了更多关于 JS 垃圾收集的内容后,我意识到这是一个棘手的问题。在 JavaScript 中,无法像在其他一些语言中那样显式地“处置”对象。当 Angular 销毁一个组件时,它会删除它的所有引用,然后垃圾收集器将它从内存中删除。 通过在订阅回调中引用它,我实际上是在告诉 GC 不要清理组件。

所以是的,Angular 在销毁组件时会“清理”组件,因为它准备组件以供 GC 删除。但是,如果该组件仍然在其他地方引用,GC 当然不会删除它。

【讨论】:

  • 是的,如果你大量使用组件,它确实会导致内存泄漏。 Angular 中的常见错误之一与订阅有关,并且忘记在 OnDestroy() 中取消订阅。
【解决方案2】:

确保在 ngOnDestroy 中进行清理,不会出现此问题。

您必须像这样取消订阅:

sub = this.myService.getObservable().subscribe();

ngOnDestroy(): void {
  this.sub.unsubscribe();
}

如果您不这样做,您将遇到您面临的问题,并且订阅将继续发送。对于 Angular 新手来说,这是一个很大的问题。

当一个组件有多个订阅并且使用 RxJS 运算符 takeUntil 有更好的模式和更少的代码脚手架时,这种模式会变得很烦人。

您还必须确保在销毁组件时在任何活动间隔或超时时调用 clearInterval 和 clearTimeout。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-15
    • 2020-02-17
    • 1970-01-01
    • 1970-01-01
    • 2018-01-26
    • 2019-08-31
    • 1970-01-01
    相关资源
    最近更新 更多