Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/451.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby-on-rails-4/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
是否可以创建不拥有JavaScript订阅的事件发射器?_Javascript_Event Handling_Weak References_Eventemitter - Fatal编程技术网

是否可以创建不拥有JavaScript订阅的事件发射器?

是否可以创建不拥有JavaScript订阅的事件发射器?,javascript,event-handling,weak-references,eventemitter,Javascript,Event Handling,Weak References,Eventemitter,假设我们有一些系统的模块(M)和事件发射器(E),它们提供了一些M需要的更新。 当M订阅E时,它将回调函数(F)传递给E。在这一点上,E将引用F,F将引用M(E)→ F→ M) 。这意味着由于事件发射器的原因,无法对M进行垃圾收集。但是从概念上讲,当M在整个系统中变得不被引用时,它不需要E的任何更新,因此E不应该阻止它被垃圾收集 在今天的JavaScript订阅模型中,它是通过返回显式处理器(DF)来解决的,DF是一个为特定订阅执行取消订阅的函数。但我认为这不好有两个原因。首先,它打破了Java

假设我们有一些系统的模块(M)和事件发射器(E),它们提供了一些M需要的更新。 当M订阅E时,它将回调函数(F)传递给E。在这一点上,E将引用F,F将引用M(E)→ F→ M) 。这意味着由于事件发射器的原因,无法对M进行垃圾收集。但是从概念上讲,当M在整个系统中变得不被引用时,它不需要E的任何更新,因此E不应该阻止它被垃圾收集

在今天的JavaScript订阅模型中,它是通过返回显式处理器(DF)来解决的,DF是一个为特定订阅执行取消订阅的函数。但我认为这不好有两个原因。首先,它打破了JavaScript的自然规则:当引用无法访问某个对象时,该对象将被垃圾收集。第二,disposer是另一个参考。现在DF引用了E,因此不仅E阻止M来自gc,反之亦然(M→ DF→ E和E→ F→ M)

这似乎是一个使用弱引用的好地方。然而,我无法解释如何在WeakMap或WeakSet之上构建事件发射器。 即使您将订阅放在弱容器中,您仍然需要一些硬引用,以便在需要发出时将其取出。这完全抵消了弱容器的好处

我最好的想法是一个假设的“支持迭代的弱点集”。除了通常的API:
add
delete
这样的对象应该有
forEachWeak
,它只适用于普通的forEach并授予对迭代对象的临时所有权。若用户不想将这些对象提取到其他硬引用容器(如数组)中,这并没有打破引用的弱点,并且仍然允许对其进行迭代。在事件发射器的情况下,这样的发射器将能够向子选项发出更新,而无需永久引用它们

那么,是否有可能以这种或任何其他方式构建非所有者事件发射器

但是从概念上讲,当M在整个系统中变得不被引用时,它不需要E的任何更新

那要看情况。只有当M完全是被动的时,这才有效。只要您想使用M实际执行某些操作,您就需要它来获取更新,而不管其他任何东西是否引用它。通过将M存储在全局变量(?)中来保持订阅的活动性,并通过尝试将其垃圾收集(这是不确定的)来取消订阅是相当困难的。另一方面,一个明确的处理器是清晰而简单的

我无法想象如何在WeakMap或WeakSet之上构建事件发射器


这是不可能的。WeakMap/WeakSet实际上是,它们不提供。

可能。这样做,我会将我的答案更新为“是”:我仍然很好奇,你有没有遇到过这样的问题?>通过将m存储在全局变量(?)中来保持订阅的活动性,事实上,是的。在任何应用程序中,M要么是其他M*的子系统(由硬引用引用),要么是顶级实体(实际上是全局的)。当子系统不能被ref访问时,它们自然会被垃圾收集。假设“弱发射极”将在无法从顶层M*访问时立即失去对M的引用。所以,取消订阅仍然是确定的、即时的,并且没有disposer(gc将在稍后进行)。但我评估您对disposer的明确性的看法。我唯一的想法是,明确取消订阅任何内容的要求可能只是缺少弱发射器的结果。如果此类API基于弱发射器,则取消订阅将遵循与丢失对子系统的引用相同的规则。“在任何应用程序中,M要么是其他M的子系统(由硬引用引用),要么是顶级实体(实际上是全局的)*”-在我对js应用程序的经验中,不是。例如,在标准nodejs http服务器中,主脚本将创建一个服务器对象并注册它(或其在对象上形成闭包的方法),以处理来自事件循环的请求事件。对象不存储在任何位置(在全局变量中),使其保持活动状态的只是来自event loop.contd'的引用。您可能能够为整个静态“子系统”(我想到的是类似于单例的服务对象)实现这一点,例如,通过将它们从各自的模块中导出,将模块系统作为全局服务注册表;尽管如果它们是静态的(在整个应用程序生命周期中保持不变),那么每周引用它们是毫无意义的。contd。我认为它根本不适用于动态创建的监听器(希望得到通知的对象)——这些监听器通常只从它们注册的发射器引用。如果这些很弱,它就不起作用了。如果您从静态模块中硬引用它们,就会造成内存泄漏——或者您必须显式管理它们(删除它们的硬引用),在这种情况下,您还可以返回显式处理器(或事件取消订阅)。