React Flux调度器vs Node.js EventEmitter – 可扩展?

当你使用Node的EventEmitter时,你订阅一个事件。 您的callback仅在特定事件启动时执行:

eventBus.on('some-event', function(data){ // data is specific to 'some-event' }); 

在Flux中,您向调度员注册您的商店,然后当每个事件被调度时,您的商店被调用。 商店的任务是过滤每一个事件,并确定事件对商店是否重要:

 eventBus.register(function(data){ switch(data.type){ case 'some-event': // now data is specific to 'some-event' break; } }); 

主持人在录像中说:

实际上,所有商店都会收到所有的动作,这就是保持可扩展性的原因。“

为什么以及如何向每个商店发送每个动作(大概)比只向特定商店发送动作更具可扩展性?

这里提到的可伸缩性更多的是扩展代码库,而不是缩放软件的速度。 stream量系统中的数据很容易追踪,因为每个商店都被注册到每个操作中,并且这些操作定义了系统中可能发生的每个应用程序范围内的事件。 每个商店都可以确定如何更新自己以响应每个操作,而不需要程序员决定哪些存储库连接哪些操作,并且在大多数情况下,您可以更改或读取商店的代码,而无需担心关于它如何影响任何其他商店。

程序员有时需要注册商店。 商店对于从事件中获得的数据非常具体。 在注册特定事件的过程中,如何更好地查找商店内的数据,并让商店始终期望它所需要/关心的数据?

系统中的操作代表系统中可能发生的事件,以及该事件的相关数据。 例如:

  • 用户login; 附带用户configuration文件
  • 用户添加了评论; 附带评论数据,它被添加到的项目ID
  • 用户更新了post; 附带发布数据

所以,你可以把行动看作商店可以知道的事情的数据库。 任何时候发送一个动作,它都被发送到每个商店。 所以,在任何时候,你只需要一次考虑你的数据突变一个商店+行动。

例如,当一个post被更新时,你可能有一个PostStorePOST_UPDATED动作,当它看到它时,它将更新它的内部状态来存储新的post。 这与任何其他可能关心POST_UPDATED事件的商店都是完全分开的,任何其他从事该应用程序的团队的程序员都可以单独作出决定,知道他们能够挂钩到数据库中的任何操作可能发生的行为。

另一个原因是在代码库方面是有用的和可扩展的,这是控制的反转; 每家商店决定它关心的行为以及如何回应每个行动; 所有的数据逻辑都集中在那个商店里。 这与MVC模式相反,在这种模式中,控制器被明确设置为在模型上调用变异方法,并且一个或多个其他控制器可以在同一时间(或不同时间)调用相同模型上的变异方法。 数据更新逻辑通过系统传播,理解数据stream需要理解模型可能更新的每个地方。

最后,还有一点需要注意的是,注册与不注册是一个语义问题。 抽象出商店接受所有行为的事实是微不足道的。 例如,在Fluxxor中,商店有一个名为bindActions的方法, bindActions特定的操作绑定到特定的callbackbindActions

 this.bindActions( "FIRST_ACTION_TYPE", this.handleFirstActionType, "OTHER_ACTION_TYPE", this.handleOtherActionType ); 

即使商店接收到所有操作,在内部映射下查找内部映射中的操作types,并在商店中调用适当的callback。

我一直在问自己同样的问题,不能从技术上看到注册如何增加了很多,超出了简化。 我会提出我对系统的理解,希望如果我错了,我可以纠正。

TLDR; EventEmitter和Dispatcher具有类似的用途(pub / sub),但将精力集中在不同的function上。 具体来说,“waitFor”function(允许一个事件处理程序确保已经调用另一个事件处理程序)不能用于EventEmitter。 调度员专注于“waitFor”function。


该系统的最终结果是与商店沟通已经发生了一个行动。 商店是否“订阅所有事件,然后过滤”或“订阅特定事件”(在调度员处进行过滤)。 不应该影响最终的结果。 数据在您的应用程序中传输。 (处理程序总是只启动事件types和进程,例如它不希望在所有事件上运行)

正如你所说的“程序员有时需要注册商店”。 这只是订阅忠诚的问题。 例如,我认为保真度的改变不会对“控制倒置”产生任何影响。

Facebook的Dispatcher中增加的(杀手)function是能够“等待”另一家商店,首先处理事件。 问题是,这个function是否要求每个商店只有一个事件处理程序?

我们来看看这个过程。 当你在Dispatcher上发送一个动作的时候(省略一些细节):

  • 迭代所有注册的订户(到调度员)
  • 调用注册callback(每个商店一个)
  • 该callback可以调用“waitfor()”,并传递一个“dispatchId”。 这在内部引用由不同商店注册的callback。 这是同步执行的,导致其他商店接收行动,并首先更新。 这要求在处理动作的代码之前调用“waitFor()”。
  • 由'waitFor'调用的callback切换动作types来执行正确的代码。
  • callback现在可以运行其代码,知道其依赖关系(其他商店)已经被更新。
  • callback开关的动作“types”执行正确的代码。

这似乎是一个非常简单的方法来允许事件依赖。

基本上所有的callback最终都是以特定的顺序调用的。 然后切换到只执行特定的代码。 所以,就好像我们只是按照正确的顺序在每个商店触发了“add-item”事件的处理程序。

如果在callback级别(而不是“商店”级别)的订阅,这仍然是可能的? 这将意味着:

  • 每个商店将注册多个callback特定的事件,保持参考他们的“dispatchTokens”(与目前相同)
  • 每个callback将有自己的“dispatchToken”
  • 用户仍然会“等待”特定的callback,但是成为特定商店的特定处理程序
  • 调度员然后将只需要以相同的顺序发送特定动作的callback

Facebook上的聪明人可能已经发现,这实际上不会增加​​个人callback的复杂性,或者可能不是优先考虑的事情。

Interesting Posts