FLUX中异步请求应不应该放Store中?


个人认为是应该放在 Action Creator 层的,但是时常会见到由 Store 负责API请求的flux实现。

之前我以为这是很多人受MV*的Model影响,把Store也当作了面向Server的数据代理

但是随着越来越多的见到这种用法。甚至上上周六在UPYUN举办的 线下活动 中,豆瓣的著名大牛@张克军 前辈在流程图中也将API调用交给了 Store ,如下图:
图片描述

当前最流行的FLUX实现 reflux 的推荐示例 react-news 也将异步的数据操作放在了 store 中。

与此同时,Facebook的态度似乎有一些摇摆:

在在React官网的Blog中,有这么一篇介绍Flux的文章: Flux: Actions and the Dispatcher ,其中出现的配图如下:
flux-diagram.png
上图的观点很明显: API请求应该由Action Creator负责

然而,在后来FLUX官网的“整理版” 同名文章 中,却去掉了上图,取而代之的是没有标注Web API的流传的最广的那张流程图。这实在是有些另人费解。

从个人的理解而言,Store代表了整个应用的当前状态。而Action则代表了对整个系统的输入,即可能改变应用状态的两类行为:

  • user interaction
  • server response

由于API操作可能会改变应用状态,他应该以Action的形式输入FLUX系统,而不是被Store内部消化。

当Store不包含异步逻辑时,对每一次Action输入,Store的变更都是确定的,整个应用也因此变得更加可预测, action输入--dispatcher分发--store处理--视图渲染 也是非常完美的单向数据流动。

而如果在Store中发起API请求,每次请求至少有成功与失败两种状态,级联时可能状态更是指数上升。如果每次action产生的状态变更是无法确定的,FLUX反复强调的可预测和单向数据流要如何体现呢?

最后的总结下问题:

  1. FLUX中异步请求应不应该放Store中?
  2. 如果应该放在Store中,为什么?

@题叶 我看到你在Flux的issue中有过相关问题和讨论,最后结果似乎也是更应该放在Store之外?

reactjs reflux flux

带胶布撕鸡 10 years, 1 month ago

大部分数据的唯一真相(SSoT)在后端,前端的Store只需要也只应该把后端的数据显示出来,作为缓存之类。
为了显示这类数据而做的请求可以放在Store里面,因为是不应该失败的请求。
同意你的其他观点。

羽川恋恋猫 answered 10 years, 1 month ago

我们在简聊的实践当中 Ajax 是放在 Action Creator 大致的位置的.

我倾向于这样去理解:
一个应用有 Store, 有 View,
View 跟着 Store 更新, View 上的 Action 会引起 Store 的更新.
当出现网络请求的时候, 问题不是网络请求是哪个部分, 而是 为什么需要网络请求?
更全局的看法是, 服务器上的数据库是 Store, 前端的界面是 View,
因为当前技术的限制, Store 和 View 之间有巨大的延时, 只能在前端缓存一份 Store.
这样理解, 我认为网络请求是发送 Action 到 Store 的一个过程,
对应在 Action Creator 当中做处理.

ntower answered 10 years, 1 month ago

首先,不是所有对数据的请求都是要通过 Store 的。无需在 Components 之间重用的数据,则可以让 Component 自己去获取,例如:搜索时的 Auto Complete 数据查询。这种 sideway 数据未来的获取方法的讨论在 https://github.com/facebook/react/issues/3398
需要在 Components 之间分享的数据,则可以通过 Store 来获取,反过来通过事件通知 Component。
如果不仅想获取数据,而且也要获得调用失败的状态,那么定义专门表示错误状态的事件虽然可行,但是却会造成 Component 内的订阅代码冗余和状态混乱。
Reflux 解决这个问题的方法是,用 action 模拟 Promise。Component 可以用 someAction.triggerPromise().then/.catch 这样的方式来触发 action,获得结果或者获得错误。Store 则负责监听 someAction ,获得数据后调用 somaAction.completed(result) 触发代表成功的 someAction.completed (这其实也是一个 action);失败了则触发 someAction.failed 。Reflux 负责将这三个 actions (实际是三个有父子关系的事件类型) 通过 triggerPromise 包装成了 Promise。
Reflux 可以包含支持 Flux 的模式(例如,Store trigger event 来通知数据变化),但是并不限定死调用模式,遇到更多需求的时候,其灵活性要强得多。因为其本质是一套 Pub/Sub 系统,但是添加了一定程度的模拟 RPC 的语法糖,以及 React 的 Mixins。

MARIKA answered 10 years, 1 month ago

Your Answer