【问题标题】:Does one need to unsubscribe form event based on fromEvent是否需要根据 fromEvent 取消订阅表单事件
【发布时间】:2019-08-15 19:56:50
【问题描述】:

是否需要基于控件取消订阅事件。

HTML输入:

  const blur$ = fromEvent(formEle, 'blur').subscribe(x => {
    this.focused = false;
  });

表单组:

  const valChanges$ = this.fGroupRef.get('first_name').valueChanges.subscribe(val => {
  this.hasValue = !!val;
  });

寻求更深入地了解这里发生的事情:

这两个订阅都基于在离开控件时将被销毁的控件事件。订阅不会取消订阅,因为它不会引用任何内容吗? ―或―订阅本身是否会创建对所述控件的引用,从而无法进行垃圾收集?

更新忘了说:在我的测试中我发现 blur$ 在组件销毁后是未定义的,如果取消订阅会抛出错误。但是, valChanges$.unsubscribe() 不会引发错误,但它们都是同一组件的一部分。

【问题讨论】:

  • 创建订阅只要它没有被取消订阅,它就会在框架中保持打开状态。很少有例外情况存在,例如 HTTP 调用,一旦请求完成,这些调用就会结束。据我所知,事件需要取消订阅,因为它们很热:它们对对应于可观察对象的每个事件做出反应。

标签: angular rxjs


【解决方案1】:

不,如果目标元素被销毁,您不需要取消订阅。如果元素被销毁,则所有事件侦听器也会按照If a DOM Element is removed, are its listeners also removed from memory?

被销毁

您的事件监听器不会阻止元素被破坏。如果您继续订阅(从subscribe 返回),它将一直存在,直到您不再引用它。一旦你停止引用它,它也会被清理。

如果您有任何complete 订阅,它们将不会被解雇。 observable 没有“完成”它只是不再触发。

编辑:必须的,如果您自己不取消订阅,那么您无法控制最后一个事件何时触发,这可能是在清理组件之后但在实际删除元素之前,因此您的订阅可能会触发当您的组件处于不确定状态时。

【讨论】:

    【解决方案2】:

    如果您阅读FromEventObservable 的源代码和文档,您会发现它只是在事件目标元素上添加/删除事件回调。当目标元素在取消订阅 observable 之前以某种方式被破坏时,回调将永远不会再次执行。然而,observable 本身在技术上仍将被“订阅”并等待更多事件。

    没有适当的机制来观察事件目标“存在”本身并为您自动取消订阅可观察对象。

    FromEventObservable 也尝试尽可能通用。它不希望您的目标是 HTML DOM 节点。

    最低期望是,您的目标具有addEventListenerremoveEventListener 方法。这意味着它无法跟踪理论上的“元素被移除/销毁事件”。 FromEventObservable 理论上可以检测 HTML 节点并对其进行特殊处理,但这会导致不同目标类型之间的行为不一致。

    TL;DR

    是的,您应该这样做,因为 RxJS 不知道已删除的事件目标。

    【讨论】:

    • 我不遵循你的推理。鉴于 FromEventObservable 只是向元素添加了一个事件侦听器,唯一引用观察者的是 DOM 元素,如果元素从 DOM 中删除,则不再(不应该)引用它,因此它将是垃圾-与它的听众一起收集,因此与可观察者及其观察者一起收集。因此,除非浏览器有问题并在您在删除元素之前不删除侦听器时导致内存泄漏,否则您不必取消订阅。
    • @JBNizet 我试图解释保持订阅不会造成任何真正的伤害,因为不会有任何新事件,但您仍然应该取消订阅以离开“订阅”状态。实例是否从内存中删除是另一回事。明确取消订阅也会告诉其他团队成员和你未来的自己,你已经完成了那个 observable。它还将它告诉 RxJS 库。图书馆可以用它来做一些聪明的事情,比如清理。即使它现在不做聪明的事情,未来的版本可能会做。经验法则:按预期使用任何给定的界面。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-12
    • 2018-07-23
    • 2021-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多