React Flux调度程序与Node.js EventEmitter - 可扩展?

时间:2015-06-20 15:23:07

标签: node.js design-patterns reactjs flux eventemitter

使用Node的EventEmitter时,您订阅了一个事件。只有在特定事件被触发时才会执行回调:

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;
   }
});

In this video,主持人说:

  

“商店订阅操作。实际上,所有商店都接收所有操作,这就是保持其可扩展性的原因。”

问题

为什么以及如何将每个操作发送到每个商店[推测]比仅向特定商店发送操作更具可扩展性?

2 个答案:

答案 0 :(得分:6)

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

  

在某些时候程序员需要注册商店。该商店非常特定于它将从活动中收到的数据。如何更好地查找商店内的数据而不是注册特定事件,并让商店始终期望它需要/关心的数据?

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

  • 用户已登录;附带用户个人资料
  • 用户添加了评论;附带评论数据,项目ID已添加到
  • 用户更新了帖子;附带发布数据

因此,您可以将操作视为商店可以了解的事物数据库。每次调度操作时,都会将其发送到每个商店。因此,在任何给定时间,您只需要一次考虑单个商店+操作的数据突变。

例如,当帖子更新时,您可能会PostStore监视POST_UPDATED操作,当它看到时,它会更新其内部状态以存储新帖子。这与任何其他可能也关心POST_UPDATED事件的商店完全分开 - 任何其他在应用程序上工作的团队的任何其他程序员都可以单独做出决定,并知道他们能够挂钩任何行动在可能发生的行动数据库中。

这在代码库方面有用且可扩展的另一个原因是控制反转;每个商店决定它关心的如何响应每个动作;所有数据逻辑都集中在该商店中。这与MVC这样的模式形成对比,MVC中的控制器被明确设置为在模型上调用变异方法,并且一个或多个其他控制器也调用变异方法在相同的模型上同时(或不同的时间);数据更新逻辑通过系统传播,理解数据流需要了解模型可能更新的每个位置。

最后,要记住的另一件事是注册与不注册是一种语义问题;抽象商店收到所有行动这一事实是微不足道的。例如,在Fluxxor中,商店有一个名为bindActions的方法,它将特定操作绑定到特定的回调:

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

即使商店收到所有操作,它也会在内部地图中查找操作类型并在商店中调用相应的回调。

答案 1 :(得分:2)

我一直在问自己同样的问题,并且无法从技术上看到注册如何增加,超出简化范围。我将提出我对系统的理解,希望如果我错了,我可以纠正。

TLDR; EventEmitter和Dispatcher提供类似的用途(pub / sub),但他们的工作重点是不同的功能。具体而言,等待' EventEmitter不提供功能(允许一个事件处理程序确保已经调用了另一个事件处理程序)。 Dispatcher的工作重点是“等待”和“等待”。特征。

系统的最终结果是与商店沟通已发生的操作。商店是否订阅所有活动,然后过滤'或者'订阅特定活动' (在调度员处过滤)。不应影响最终结果。数据在您的应用程序中传输。 (处理程序始终只打开事件类型和进程,例如,它不想对所有事件进行操作)

正如你所说"在某些时候程序员需要注册商店。"。这只是订阅保真度的问题。我不认为保真度的变化会对控制权的反转产生任何影响。例如。

facebook的调度员增加(杀手)功能是它能够等待'一个不同的商店,首先处理事件。问题是,此功能是否要求每个商店只有一个事件处理程序?

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

  • 迭代所有注册用户(向调度员)
  • 调用已注册的回调(每个商店一个)
  • 回调可以调用' waitfor()',然后传递' dispatchId'。这内部引用了由不同商店注册的回调。这是同步执行的,导致其他商店接收操作并首先更新。这需要“等待()'在处理操作的代码之前调用。
  • ' waitFor'打开操作类型以执行正确的代码。
  • 回调现在可以运行其代码,知道其依赖性(其他商店)已经更新。
  • 回调会切换操作'类型'执行正确的代码。

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

基本上所有的回调最终都会被调用,但是按照特定的顺序。然后切换到仅执行特定代码。所以,就好像我们只触发了一个' add-item'每个商店的活动,顺序正确。

如果订阅位于回调级别(不是'存储'级别),这仍然可能吗?这意味着:

  • 每家商店都会注册多个特定活动的回调,并参考他们的发送动作。 (与目前相同)
  • 每个回调都有自己的' dispatchToken'
  • 用户仍然会等待#39;特定的回调,但是特定商店的特定处理程序
  • 然后,调度员只需要以相同的顺序发送到特定操作的回调

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