在 JavaScript 中,观察者模式经常被使用。其中有一件棘手的事情,那就是主体保留观察者的参考资料。他们需要清理。对于常规应用程序,我使用以下经验法则:
- 如果主体的寿命短于(或等于)观察者,我可以这样做
subject.on('event', ...)
- 如果主体的寿命比观察者长,我需要使用
observer.listenTo(subject, 'event', ...)
在第二种情况下,listenTo
知道观察者的生命周期,当观察者死亡时,它会自动删除监听者。
在现代 SPA(单页应用程序)风格中,任何时候只有应用程序的一部分处于活动状态,这一点变得非常重要。如果将其与网络套接字(它是事件流的完美候选者并且很可能长期存在)结合起来,这一点就变得更加重要。
使用 FRP,拥有类似代表随时间变化的值的事件流之类的东西,我(在不知情的情况下)创建了很多侦听器。每个filter
, map
and flatMap
创建一个与前一个流绑定(可能使用侦听器)的新流。
在我看来,确定如何以及何时需要删除这些侦听器似乎相当棘手。我无法想象我是第一个想到这个问题的人,但我在互联网上找不到太多关于这个问题的信息。
我见过其他语言中的一些框架使用弱引用。 JavaScript 没有弱引用的概念(WeakMap 在这里无法使用)。即使有,这似乎也是一个坏主意,因为尚不清楚垃圾收集何时发生。
- 在当前的框架中如何解决这个问题?
- 框架是否与对象的生命周期相关?如果是:怎么办?
在 RxJ 中,每个Observer
默认情况下,原始事件源上有一个单独的侦听器。所以,如果你有
var s = $('#textInput').keyupAsObservable()
s.subscribe(subscriber1);
s.map(function() {}).subscribe(subscriber2);
您将有两个 keyup 侦听器。您可以使用.publish().refCount()
做一个Observable
保持与其源的单一连接。
在 Bacon.js 中,Observables 始终保持与其源的单一连接。
在这两个库中,与源的连接都是延迟创建的(当Observer
添加)并在(最后一个)观察者被删除时自动删除。因此您不必手动管理侦听器。
然而,在这种情况下subject
寿命比Observer
,您必须确保观察者在其生命周期结束时停止其订阅,否则就会发生泄漏。两个图书馆都没有任何“神奇”的方式来管理这个问题,因为对于图书馆来说,你的Observer
只是一个函数。
我个人经常创建一个Observable
called death
或任何表明观察者寿命结束的信号,然后而不是订阅subject
我订阅subject.takeUntil(death)
.
对于Elm,我的理解是,你一次性建立了整个事件网络,所以不存在泄漏的可能性;Observers
无法在后期添加。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)