用于乐观更新的操作存储是 Redux/Flux 中的一个好方法吗?

2024-01-03

我一直在 React+Flux 应用程序中进行乐观更新,并看到了两件事:

  1. 如果用户在存在某些未完成的操作时尝试关闭窗口,会发生什么情况。例如,在 Facebook 中,即使没有真正持久化,消息也会出现在墙上(这就是乐观更新的作用,对用户来说是一个响应更快的应用程序)。但是,如果用户在留言墙上发帖并立即关闭应用程序(注销或窗口关闭时),则该发帖可能会失败并且不会收到警报。
  2. 我不喜欢商店管理自己的实体(例如消息)的想法以及为持久化消息而触发的操作的情况(加载、成功、失败?)。它混合了东西。

所以我致力于此并创建一个行动商店管理组件触发的操作的状态。Here is https://github.com/gabrielgiussi/redux_actionsStore源代码和here is http://www.googledrive.com/host/0Bw73nZfYKsXNfkY4T2xWLTktQW8tWV92UVBULUNzQXpuazdRYTVicEhpQlFXcW1NMTVlalk现场演示。

它的工作原理或多或少像这样:

  1. 组件层次结构的根(redux 中的容器)获取新操作的 nextId 并将其像 props 一样传递给他的子级(这很丑陋)。
  2. 子组件触发一个操作:它保留 actionId,以便在之后将其请求到存储并调用操作创建者。
  3. 动作创建者创建一个新的动作并向中间件返回一个函数。
  4. 从 Action 返回的函数通过 API 调用创建一个新的 Promise,并分派 XX_START 类型的操作。
  5. ActionStore 监听 XX_START 操作并保存它。
  6. 子组件接收新状态并找到具有保存的 id 的操作并询问当前情况:加载、成功或失败。

我这样做主要是为了将“实体”的状态与操作的状态分开,但也允许使用相同的负载重新触发操作(当我们收到 500 响应状态时,如果服务器暂时关闭或如果用户丢失信号)。

此外,拥有操作存储可以在用户注销或关闭窗口之前轻松询问它们是否是待处理的操作。

注意:我正在针对 Rest API 使用单应用程序页面 Web 应用程序,我不认为在服务器端渲染上使用它

创建 ActionStore 是一个可行的选择,还是我破坏了一些 Redux/Flux 基础? 这可能会结束使用 React 热重载和时间旅行的可能性吗?

你应该毫不留情地回答,我可能做了很多丑陋的事情,但我正在学习 React/Redux。


对于可能有点困惑的未来读者:我们不再称这些函数为“存储”:我们称它们为“存储”reducers http://rackt.github.io/redux/docs/basics/index.html。所以问题是关于一个记住动作的减速器 https://github.com/gabrielgiussi/redux_actionsStore/blob/2e948b8ea616ea9f1289d0b6e5d2f60d82545f11/js/src/common/ActionStore.js.

就我个人而言,我不喜欢你在那里建议的方法。您将逻辑放入操作中并为此使用继承。相反,Redux 将操作规定为没有逻辑的普通对象。他们不应该“知道”如何更新某些状态,也不应该保留它——相反,他们应该描述发生了什么。

我认为在 Redux 中实现乐观更新的方法与您的方法类似在 Redux 中实现撤销 https://github.com/omnidan/redux-undo,这反过来又受到启发榆树建筑 https://github.com/evancz/elm-architecture-tutorial/。这个想法是,您应该编写一个函数,它接受一个减速器(和一些选项)并返回一个减速器:

function optimistic(reducer) {
  return function (state, action) {
    // do something?
    return reducer(state, action);
  }
}

你可以像普通的减速器一样使用它:

export default combineReducers({
  something: optimistic(something) // wrap "something" reducer
})

现在它只是将状态和操作传递给reducer它会包装,但它也可以“记住”动作:

function optimistic(reducer) {
  return function (state = { history: [] }, action) {
    // do something with history?
    return {
      history: [...state.history, action],
      present: reducer(state.history[state.history.length - 1], action)
    };
  }
}

现在它累积了所有动作history field.

同样,这本身并不是很有用,但您可能会看到如何实现这样的高阶减速器:

  • 通过 ID 跟踪待处理的异步操作,并在看到带有以下内容的操作时开始记录历史记录status: 'request';
  • 当它收到一个动作时status: 'done',重置历史记录;
  • 当它收到一个动作时status: 'fail',调整历史记录以不包括初始操作status: 'request' and 重新运行减速器以重新计算当前状态,就好像请求从未发生过一样。

当然,我没有提供实现,但这应该让您了解如何以 Redux 方式实现乐观更新。

更新:根据OP的评论,还原乐观主义者 https://github.com/ForbesLindesay/redux-optimist似乎正是这样做的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用于乐观更新的操作存储是 Redux/Flux 中的一个好方法吗? 的相关文章

随机推荐

  • IIS 7.5 在哪里记录错误?

    IIS 7 5 在哪里记录错误 事件查看器 日志档案 我收到一个非常不具体的内部 500 错误 我想了解更多 我正在运行 PHP 我做了什么最后一条评论 http forums iis net t 1169733 aspx在这个帖子上说 但
  • 检测直角三角形的C程序

    如果给我坐标系中的 100 个点 我必须找出这些顶点中是否存在直角三角形 有没有一种方法可以检测这些顶点中的直角三角形 而不必选择所有 3 个顶点对 然后对它们应用毕达哥拉斯定理 有更好的算法吗 谢谢你的帮助 这是一个O n 2 log n
  • 对绑定到 DataTable 的 GridView 进行排序

    我有一个存储库 其中包含我正在处理的这个项目的所有 LINQ 查询 我能够将 LINQ 结果获取到 DataTable 并将其绑定到 gridview 以显示数据 现在我需要使 gridview 可排序 我已经设定AllowSorting
  • 如何确定 Git 中合并提交的第一个父级

    我正在阅读有关使用的差异 vs git 中的运算符 我遇到了这个问题Git 中的 HEAD 和 HEAD 有什么区别 https stackoverflow com q 2221658 2498327 在谷歌搜索后 我在网上找不到一个很好的
  • 当我有触摸事件处理程序时,为什么我的鼠标事件处理程序不工作?

    我的一些最终用户拥有触摸屏 其他用户则拥有 PC 在触摸屏上 PreviewMouseUp Down与触摸事件处理程序一起触发 导致重复行为 在 PreviewMousUp Down 中编写的函数被执行两次 所以我的示例按钮 XAML
  • 当涉及两个输入时,jQuery 模糊不断触发

    我在 Google 和 Stack Overflow 上搜索了一段时间 但找不到与此相关的任何内容 我有多个输入文本字段 当模糊时 它们会向服务器调用 jQuery AJAX 函数 它几乎可以完美地工作 问题是 如果我专注于一个文本输入 然
  • 为什么 Set 与 Proxy 不兼容?

    JavaScriptSet https developer mozilla org en docs Web JavaScript Reference Global Objects Set似乎与 JavaScript 完全不兼容proxies
  • Pymongo 连接远程机器超时

    我有一个在 AWS EC2 上运行的 Bitnami MEAN 堆栈 我正在尝试使用 PyMongo 从远程计算机进行连接 from pymongo import MongoClient conn MongoClient mongodb u
  • Automapper:忽略条件

    是否可以根据源属性的值忽略映射成员 例如 如果我们有 public class Car public int Id get set public string Code get set public class CarViewModel p
  • 可以要求我的事件处理程序立即返回吗?

    我正在编写一个 NET 库 其中一个类包含库用户需要订阅的事件 是否可以要求这些事件的处理程序的实现快速返回 或者这是一个有共同解决方案的常见问题吗 如果处理程序花费很长时间 这不会是致命的 但如果处理程序花费的时间超过大约半秒 事情就会开
  • Angular 5 - 添加动态路由但不路由

    我创建了一个新项目 并向路由模块添加了一些代码以进行动态路由 路由模块代码如下 import NgModule from angular core import Routes RouterModule Router from angular
  • SSRS 和 PowerShell:获取 Excel 格式的报告

    我正在尝试让 PowerShell 向我们的 SSRS 服务器发送 Web 请求并捕获结果 我已经使用了撞墙rs FORMAT EXCELSSRS url 字符串中的参数 我有以下内容 首先 初始化凭据 User MYDOMAIN MyUs
  • jquery 插件在其他公共函数中调用公共函数

    我定义了我的插件基于http docs jquery com Plugins Authoring http docs jquery com Plugins Authoring function var methods init functi
  • 使用 httplib 进行不完整读取

    我在从特定网站获取 RSS 提要时一直遇到问题 我最终编写了一个相当丑陋的程序来执行此功能 但我很好奇为什么会发生这种情况以及是否有更高级别的接口正确处理此问题 这个问题并不是真正的问题 因为我不需要经常检索提要 我已经阅读了一个捕获异常并
  • AngularJS Protractor E2E 模拟

    我有一个 Angular SPA 从节点后端检索其数据 由于节点项目完全覆盖了测试 我想模拟 Angular HTTP 调用 我不想开始讨论一般的功能 冒烟测试 谢谢 我想要的是 像这样 Api injector get Api sinon
  • 按位 XOR(异或)是什么意思?

    我试图理解 C 或一般情况下的二元运算符 特别是 异或 http msdn microsoft com en us library zkacc7k1 aspx 例如 给定一个正整数数组 除了一个出现奇数次的数字外 所有数字都出现偶数次 在
  • nodejs socket.io 在函数循环内发出

    我想通过循环内的 socket io 发出 为此 我制作了一个运行良好的触发器 但在每个触发器中我调用 socket emit 并且只有第一个发出有效 这是服务器代码 var server require http createServer
  • 从动态 PHP 页面生成 HTML 静态页面 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找一个脚本来在运行时从动态内容生成静态 HTML 页面 我基本上想做的就是保存那些缓存那些ht
  • 用于提取 HTML 图像属性的正则表达式

    我需要一个正则表达式模式来提取图像标签的所有属性 众所周知 存在大量格式错误的 HTML 因此该模式必须涵盖这些可能性 我正在看这个解决方案https stackoverflow com questions 138313 how to ex
  • 用于乐观更新的操作存储是 Redux/Flux 中的一个好方法吗?

    我一直在 React Flux 应用程序中进行乐观更新 并看到了两件事 如果用户在存在某些未完成的操作时尝试关闭窗口 会发生什么情况 例如 在 Facebook 中 即使没有真正持久化 消息也会出现在墙上 这就是乐观更新的作用 对用户来说是