助焊剂存储或行动(或两者)是否应该接触外部服务?

pla*_*dan 122 reactjs reactjs-flux

如果商店保持自己的状态并且能够在这样做时调用网络和数据存储服务......在这种情况下,操作只是愚蠢的消息传递者,

-要么-

...存储是否应该是来自操作的不可变数据的愚蠢接收者(并且操作是在外部源之间获取/发送数据的操作?此实例中的存储将充当视图模型并且能够聚合/过滤它们在根据动作提供的不可变数据设置自己的状态之前的数据.

在我看来,它应该是一个或另一个(而不是两者的混合).如果是这样,为什么一个首选/推荐优于另一个?

Mic*_*ley 151

我已经看到了两种方式实现了通量模式,并且在完成了两种方式之后(最初采用前一种方法),我认为存储应该是来自操作的数据的愚蠢接收者,并且写入的异步处理应该存在于动作创作者.(可以不同地处理异步读取.)根据我的经验,这有一些好处,按重要性排序:

  1. 您的商店变得完全同步.这使您的商店逻辑更容易遵循并且非常容易测试 - 只是实例化具有某个给定状态的商店,向其发送操作,并检查状态是否按预期更改.此外,流量的核心概念之一是防止级联调度并防止一次多次调度; 当您的商店进行异步处理时,这很难做到.

  2. 所有操作调度都发生在动作创建者身上.如果您在商店中处理异步操作并且希望保持商店的操作处理程序同步(并且您应该为了获得通道单调度保证),那么您的商店将需要触发其他SUCCESS和FAIL操作以响应异步处理.将这些调度放在动作创建者中有助于分离动作创建者和商店的作业; 此外,您不必深入了解商店逻辑,以确定从哪里调度操作.在这种情况下,典型的异步操作可能看起来像这样(dispatch根据您使用的通量的风格更改调用的语法):

    someActionCreator: function(userId) {
      // Dispatch an action now so that stores that want
      // to optimistically update their state can do so.
      dispatch("SOME_ACTION", {userId: userId});
    
      // This example uses promises, but you can use Node-style
      // callbacks or whatever you want for error handling.
      SomeDataAccessLayer.doSomething(userId)
      .then(function(newData) {
        // Stores that optimistically updated may not do anything
        // with a "SUCCESS" action, but you might e.g. stop showing
        // a loading indicator, etc.
        dispatch("SOME_ACTION_SUCCESS", {userId: userId, newData: newData});
      }, function(error) {
        // Stores can roll back by watching for the error case.
        dispatch("SOME_ACTION_FAIL", {userId: userId, error: error});
      });
    }
    
    Run Code Online (Sandbox Code Playgroud)

    否则可能会在各种动作中复制的逻辑被提取到一个单独的模块中; 在这个例子中,该模块将SomeDataAccessLayer处理执行实际的Ajax请求.

  3. 你需要更少的动作创作者.这不是什么大不了的事,但很高兴.如#2中所述,如果您的商店具有同步操作调度处理(他们应该),您将需要触发额外的操作来处理异步操作的结果.在动作创建器中执行调度意味着单个动作创建者可以通过处理异步数据访问本身的结果来调度所有三种动作类型.

  • 我认为发起web api调用(action creator vs. store)的原因不如成功/错误回调应该创建一个动作的事实重要.因此,数据流始终是:action - > dispatcher - > stores - > views. (15认同)

Mar*_*pse 51

我在Facebook上向开发人员发送了这个问题,我从Bill Fisher得到的答案是:

在响应用户与UI的交互时,我会在动作创建者方法中进行异步调用.

但是当你有一个自动收报机或其他非人类驱动程序时,来自商店的电话会更好.

重要的是在错误/成功回调中创建一个动作,这样数据总是来自动作


Ryg*_*ygu 8

商店应该做所有事情,包括获取数据,以及向商店数据已更新的组件发送信号.为什么?因为动作可以是轻量的,一次性的和可更换的,而不会影响重要的行为.所有重要的行为和功能都发生在商店中.这还可以防止在两个非常相似但不同的操作中复制的行为重复.商店是(处理)真相的唯一来源.

在每个Flux实现中,我已经看到Actions基本上是事件字符串变成对象,就像传统上你有一个名为"anchor:clicked"的事件,但在Flux中它将被定义为AnchorActions.Clicked.他们甚至如此"愚蠢",以至于大多数实现都有单独的Dispatcher对象来实际将事件分派给正在监听的商店.

我个人喜欢Reflux的Flux实现,其中没有单独的Dispatcher对象,Action对象自己进行调度.


编辑:Facebook的Flux实际上是在"动作创造者"中获取,因此他们确实使用了智能动作.他们还使用商店准备有效载荷:

https://github.com/facebook/flux/blob/19a24975462234ddc583ad740354e115c20b881d/examples/flux-chat/js/actions/ChatMessageActionCreators.js#L27(27和28行)

然后,完成后的回调将触发一次新操作,并将获取的数据作为有效负载:

https://github.com/facebook/flux/blob/19a24975462234ddc583ad740354e115c20b881d/examples/flux-chat/js/utils/ChatWebAPIUtils.js#L51

所以我猜这是更好的解决方案.