在Flux应用程序中应该在哪里发出ajax请求?

Eni*_*lek 192 javascript reactjs reactjs-flux

我正在使用flux体系结构创建一个react.js应用程序,我正在尝试弄清楚应该在何时何地从服务器请求数据.这有什么例子吗?(不是TODO app!)

Mic*_*ley 126

我非常支持将异步写入操作放在动作创建者和商店中的异步读取操作中.目标是将存储状态修改代码保存在完全同步的动作处理程序中; 这使得它们易于推理并且易于单元测试.为了防止对同一端点的多个同时请求(例如,双读),我将实际的请求处理移动到一个单独的模块中,该模块使用promises来阻止多个请求; 例如:

class MyResourceDAO {
  get(id) {
    if (!this.promises[id]) {
      this.promises[id] = new Promise((resolve, reject) => {
        // ajax handling here...
      });
    } 
    return this.promises[id];
  }
}
Run Code Online (Sandbox Code Playgroud)

虽然存储中的读取涉及异步函数,但有一个重要的警告,即存储不会在异步处理程序中自行更新,而是触发操作并在响应到达时触发操作.此操作的处理程序最终会进行实际的状态修改.

例如,组件可能会:

getInitialState() {
  return { data: myStore.getSomeData(this.props.id) };
}
Run Code Online (Sandbox Code Playgroud)

商店将实现一个方法,也许是这样的:

class Store {
  getSomeData(id) {
    if (!this.cache[id]) {
      MyResurceDAO.get(id).then(this.updateFromServer);
      this.cache[id] = LOADING_TOKEN;
      // LOADING_TOKEN is a unique value of some kind
      // that the component can use to know that the
      // value is not yet available.
    }

    return this.cache[id];
  }

  updateFromServer(response) {
    fluxDispatcher.dispatch({
      type: "DATA_FROM_SERVER",
      payload: {id: response.id, data: response}
    });
  }

  // this handles the "DATA_FROM_SERVER" action
  handleDataFromServer(action) {
    this.cache[action.payload.id] = action.payload.data;
    this.emit("change"); // or whatever you do to re-render your app
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 我发现[这个旧帖子](https://groups.google.com/forum/#!topic/reactjs/jBPHH4Q-8Sc)非常有帮助 - 特别是Bill Fisher和Jing Chen的评论.这与@BinaryMuse提出的非常接近,即调度发生在动作创建者中的细微差别. (2认同)

Seb*_*ber 37

Fluxxor有一个与API异步通信的例子.

这篇博文有关于它的讨论,并已在React的博客上发表.


我发现这是一个非常重要而且难以解决的问题,因为与后端的前端软件同步仍然很痛苦.

API请求是否应在JSX组件中生成?店?其他地方?

在商店中执行请求意味着如果2个商店对于给定的操作需要相同的数据,他们将发出2个类似的requets(除非你在商店之间引入依赖关系,我真的不喜欢)

就我而言,我发现将Q promises作为操作的有效载荷非常方便,因为:

  • 我的行为不需要序列化(我不保留事件日志,我不需要事件源的事件重放功能)
  • 它不需要具有不同的操作/事件(请求已触发/请求已完成/请求失败),并且必须在可以触发并发请求时使用关联ID匹配它们.
  • 它允许多个商店监听相同请求的完成,而不会在商店之间引入任何依赖关系(但是引入缓存层可能更好?)

Ajax是EVIL

我认为Ajax在不久的将来会越来越少使用,因为它很难推理.正确的方式?考虑到设备是分布式系统的一部分,我不知道我第一次遇到这个想法(也许在这个鼓舞人心的Chris Granger视频中).

想一想.现在为了可扩展性,我们使用具有最终一致性的分布式系统作为存储引擎(因为我们无法击败CAP定理并且通常我们希望可用).这些系统不通过相互轮询进行同步(除了可能用于共识操作?),而是使用CRDT和事件日志等结构使分布式系统的所有成员最终保持一致(成员将收集到相同的数据,给定足够的时间) .

现在想想什么是移动设备或浏览器.它只是分布式系统的成员,可能遭受网络延迟和网络分区.(即你在地铁上使用智能手机)

如果我们可以构建网络分区和网络速度容忍数据库(我的意思是我们仍然可以对隔离节点执行写操作),我们可以构建受这些概念启发的前端软件(移动或桌面),这些软件在支持的离线模式下运行良好没有应用程序的框的功能不可用.

我认为我们应该真正激发我们自己对数据库如何构建我们的前端应用程序的启发.需要注意的一点是,这些应用程序不执行POST和PUT以及GET ajax请求以将数据发送给彼此,而是使用事件日志和CRDT来确保最终的一致性.

那么为什么不在前端呢?请注意,后端已经朝着那个方向发展,像Kafka这样的工具被大玩家大量采用.这也与Event Sourcing/CQRS/DDD有关.

查看Kafka作者的这些精彩文章,说服自己:

也许我们可以从向服务器发送命令开始,并接收服务器事件流(通过例如websockets),而不是触发Ajax请求.

我从未对Ajax请求感到满意.因为我们React开发人员往往是功能程序员.我认为很难推断本地数据应该是你的前端应用程序的"真相来源",而真正的真相来源实际上是在服务器数据库上,而你的"本地"真相来源可能已经过时了当你收到它,并且永远不会收敛到真正的真值来源,除非你按下一些蹩脚的刷新按钮......这是工程吗?

然而,由于一些显而易见的原因,设计这样的东西仍然有点困难:

  • 您的移动/浏览器客户端资源有限,无法在本地存储所有数据(因此有时需要使用ajax请求重要内容进行轮询)
  • 您的客户端不应该看到分布式系统的所有数据,因此出于安全原因需要以某种方式过滤它收到的事件

  • 你能提供一个使用Q承诺与行动的例子吗? (3认同)

fis*_*dev 20

您可以在动作创建者或商店中调用数据.重要的是不直接处理响应,而是在错误/成功回调中创建一个动作.直接在商店中处理响应会导致设计更脆弱.

  • 你能更详细地解释一下吗?假设我需要从服务器加载初始数据.在控制器视图中,我启动一个动作INIT,并且Store启动它反映此动作的异步初始化.现在,我会想到,当Store获取数据时,它只会发出更改,但不会启动操作.因此,初始化后发出更改会告诉视图他们可以从商店获取数据.为什么有需要**不能**在成功加载时发出变化,但是开始另一个动作?!谢谢 (9认同)
  • 调用数据与接收数据不同.@ Jim-Y:只有在商店中的数据实际发生变化后才应该发出更改.Yotam:不,在商店中调用数据并不会打破范式.数据应仅通过操作接收,以便可以通过进入应用程序的任何新数据通知所有商店.因此我们可以在商店中调用数据,但是当响应返回时,我们需要创建一个新操作而不是直接处理它.这使应用程序保持灵活性并适应新功能开发. (4认同)