JavaScript中的功能反应式编程是否会导致侦听器引用出现更大的问题? [英] Does Functional Reactive Programming in JavaScript cause bigger problems with listener references?

查看:119
本文介绍了JavaScript中的功能反应式编程是否会导致侦听器引用出现更大的问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在JavaScript中,经常使用观察者模式。它有一个棘手的问题,那就是主体对观察者的参考。他们需要清理。对于常规应用,我使用以下经验法则:




  • 如果受试者的寿命短于(或等于)观察者,我可以做 subject.on('event',...)

  • 如果受试者的寿命超过观察者,我需要使用 observer.listenTo(subject,'event',...)



在第二种情况下, listenTo 知道观察者的生命周期,并且当观察者需要时它会自动删除监听器在现代SPA(单页应用程序)样式中,只有应用程序的某些部分在任何时候处于活动状态,这一点变得非常重要。



如果你把它与网络套接字结合起来,它是一个完美的事件流候选者,而且很可能很长寿,这就变得更加重要。



使用FRP,有类似的东西表示随时间变化的值的事件流,我(不知道)创建了大量的侦听器。每个过滤器 map flatMap 创建一个新流绑定(可能使用一个监听器)到前一个。



在我看来,确定如何以及何时需要删除这些监听器似乎相当棘手。我无法想象我是第一个考虑这个问题的人,但我在互联网上找不到这个。



我看过其他语言中的一些框架使用弱参考。 JavaScript没有弱引用的概念(WeakMap在这里不可用)。即使它有,但它似乎是一个坏主意,因为它不清楚垃圾收集何时发生。




  • 如何在当前框架中解决这个问题?

  • 框架是否与生活有关 - 对象的循环?如果是:如何?


解决方案

在RxJs中,每个 Observer <默认情况下,/ code>将在原始事件源上具有单独的侦听器。所以,如果你有

  var s = $('#textInput')。keyupAsObservable()
s.subscribe (SUBSCRIBER1);
s.map(function(){})。subscribe(subscriber2);

您将拥有两个keyup侦听器。您可以使用 .publish()。refCount()来生成 Observable 维护与其源的单个连接。 / p>

在Bacon.js中,Observables始终保持与其源的单一连接。



在两个库中连接到延迟创建源(当添加 Observer 时),并在删除(最后)观察者时自动删除。因此,您不必手动管理侦听器。



但是,如果主题的使用寿命比 Observer更长,您必须确保观察者在其生命周期结束时停止订阅,否则您将有泄漏。两个库都没有任何神奇的方法来管理它,因为对于库,你的 Observer 只是一个函数。



就个人而言,我经常创建一个名为 death Observable 或任何表示观察者生命周期结束的信号。然后而不是订阅主题我订阅了 subject.takeUntil(死亡)



关于Elm,我的理解是你已经设置了整个事件网络,所以不可能泄漏; 观察员无法在以后添加。


In JavaScript the observer pattern is used quite often. There is one tricky thing with it and that's the references the subject keeps of the observers. They require cleanup. For regular applications I use the following rules of thumb:

  • If the subject has a life span shorter than (or equal to) the observer, I can just do subject.on('event', ...)
  • If the subject has a life span longer than the observer, I need to use observer.listenTo(subject, 'event', ...)

In the second case, the listenTo is aware of the life-cycle of the observer and it will automatically remove the listeners when it's time for the observer to die.

In modern day SPA (Single Page Application) style, where only parts of the application are active at any time this is something that becomes very important. If you combine that with web sockets, which are a perfect candidate for an event stream and most likely long lived, this becomes even more important.

With FRP, having something like an event stream representing changing values over time, I am (without knowing it) creating a lot of listeners. Each filter, map and flatMap creates a new stream that is tied (probably using a listener) to the previous one.

In my mind it seems quite tricky to determine how and when I need to remove those listeners. I can not imagine me being the first to think about this problem, yet I could not find much about this on the Internet.

I have seen some frameworks in other languages use weak references. JavaScript does not have the concept of weak references (WeakMap is not usable here). Even if it had though, it seems like a bad idea because it's unclear when garbage collection takes place.

  • How is this solved in the current frameworks?
  • Do the frameworks tie into the life-cycle of objects? If yes: how?

解决方案

In RxJs, each Observer will, by default, have a separate listener on the original event source. So, if you have

var s = $('#textInput').keyupAsObservable()
s.subscribe(subscriber1);
s.map(function() {}).subscribe(subscriber2);

You'll have two keyup listeners. You can use .publish().refCount() to make an Observable maintain a single connection to its source.

In Bacon.js, Observables always maintain a single connection to their source.

In both libraries the connection to the source is created lazily (when an Observer is added) and removed automatically when the (last) Observer is removed. Therefore you don't have to manually manage the listeners.

However, in the case where the subject has a longer life span than the Observer, you'll have to make sure the observer stops its subscription when its lifespan ends, or you'll have a leak. Neither libraries have any "magical" way of managing this, because to the library, your Observer is just a function.

Personally I often create an Observable called death or whatever to signal the end-of-life for the Observer and then instead of subscribing to the subject I subscribe to subject.takeUntil(death).

Regarding Elm, my understanding is that you have set up your entire event network at once, so there's no possibility for leak; Observers cannot be added at a later stage.

这篇关于JavaScript中的功能反应式编程是否会导致侦听器引用出现更大的问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆