redux 和状态机(例如 xstate)之间的实际区别是啥?
Posted
技术标签:
【中文标题】redux 和状态机(例如 xstate)之间的实际区别是啥?【英文标题】:What is an actual difference between redux and a state machine (e.g. xstate)?redux 和状态机(例如 xstate)之间的实际区别是什么? 【发布时间】:2019-06-26 05:15:52 【问题描述】:我正在研究一种中等复杂度的前端应用程序。目前它是用纯 javascript 编写的,它有很多不同的基于事件的消息连接这个应用程序的几个主要部分。
我们决定在进一步重构的范围内为这个应用程序实现某种状态容器。之前我对 redux 和 ngrx store 有一些经验(实际上遵循相同的原则)。
Redux 是我们的一个选项,但其中一位开发人员建议使用基于状态机的库,特别是 xstate library。
我从未使用过 xstate,所以我觉得它很有趣,并开始阅读文档并查看不同的示例。看起来很有前途和强大,但在某些时候我明白我没有看到它和 redux 之间有任何显着差异。
我花了几个小时试图找到答案,或者比较 xstate 和 redux 的任何其他信息。除了 "get from redux to a state machine" 之类的一些文章,或者专注于使用 redux 和 xstate together 的库的链接(很奇怪)之外,我没有找到任何明确的信息。
如果有人可以描述差异或告诉我开发人员何时应该选择 xstate - 欢迎您。
【问题讨论】:
官方文档实际上说你应该把你的redux reducer当作一个状态机redux.js.org/style-guide/… 我认为您提到的库可能是用于使用 xstate 作为效果管理系统(替代 thunk、saga、epic 等) 【参考方案1】:我创建了 XState,但我不会告诉你是否要使用其中一个;这取决于你的团队。相反,我将尝试强调一些关键差异。
Redux | XState |
---|---|
essentially a state container where events (called actions in Redux) are sent to a reducer which update state | also a state container, but separates finite state (e.g., "loading" , "success" ) from "infinite state", or context (e.g., items: [...] ) |
does not dictate how you define your reducers - they are plain functions that return the next state given the current state and event (action) | a "reducer with rules" - you define legal transitions between finite states due to events, and also which actions should be executed in a transition (or on entry/exit from a state) |
does not have a built-in way to handle side-effects; there are many community options, like redux-thunk, redux-saga, etc. | makes actions (side-effects) declarative and explicit - they are part of the State object that is returned on each transition (current state + event) |
currently has no way to visualize transitions between states, since it does not discern between finite and infinite state | has a visualizer: https://statecharts.github.io/xstate-viz which is feasible due to the declarative nature |
the implicit logic/behavior represented in reducers can't be serialized declaratively (e.g., in JSON) | machine definitions, which represent logic/behavior, can be serialized to JSON, and read from JSON; this makes behavior very portable and configurable by external tools |
not strictly a state machine | adheres strictly to the W3C SCXML specification: https://www.w3.org/TR/scxml/ |
relies on the developer to manually prevent impossible states | uses statecharts to naturally define boundaries for handling events, which prevents impossible states and can be statically analyzed |
encourages the use of a single, "global" atomic store | encourages the use of an Actor-model-like approach, where there can be many hierarchical statechart/"service" instances that communicate with each other |
本周我将在文档中添加更多关键差异。
【讨论】:
终于有人使用 FSM 和 SCXML 进行前端开发......你救了我的命,我要去研究你的图书馆。由于某些原因,我不喜欢 redux(首先它混淆了事件和操作术语),其次它使用数百万个标志“建模”复杂状态(冗长且恕我直言不正确)。 @Mike76 XState 与 Redux 开发工具集成。 感谢您的提示,我会调查的。 我现在已经尝试过 XState + Redux DevTools。它工作得很好,但似乎缺少一些功能。例如,XState + Redux DevTools 不支持像“状态重放”这样的功能,即重放一系列先前的状态。这是由于实施限制吗? @Mike76 在 Redux 和 XState 的时间旅行中看到这个:github.com/statelyai/xstate/issues/906#issuecomment-569760677【参考方案2】:状态机不会告诉(强制)您拥有单向数据流。它与数据流无关。更多的是关于约束状态变化和状态转换。因此,通常只有当您需要约束/禁止某些状态更改并且您对转换感兴趣时,才会使用状态机设计应用程序的某些部分。
请注意,对于状态机,如果出于某种原因(外部 API 依赖等...),应用可能会被锁定在某个状态,由于限制而无法转换到另一个状态,您必须解决它。
但是如果您只对最后一个应用程序状态本身感兴趣,而不是状态转换,并且状态约束无关紧要,那么您最好不要使用状态机并且直接更新状态本身(您仍然可以通过 Action 类将状态包装在 Singleton 类更新中)。
另一方面,Redux 是单向架构框架。单向架构强制您拥有单一方向的数据流。在 Redux 中,它以 User->View->(Action)->Store->Reducer->(Middleware)->Store->(State)->View
开头。与状态机一样,您可以使用 Redux 中的中间件触发副作用。如果需要,您可以限制/禁止状态转换。 不同于状态机,Redux 强制单向数据流,纯! reducer 函数、不可变状态对象、单个可观察应用程序状态。
【讨论】:
FSM 不就是一个能驱动 Redux 的图吗?导航是 FSM,因为您有后退按钮。除非你禁用后退按钮,否则即使在 Redux 中,你也有一个 FSM。 Redux 是一种具有良好约束的不可变数据模式。因此,当您浏览您的 FSM(库或自己编写的,即使是无意的)时,Redux 可以防止副作用。 Redux 仅捕获数据流的单向部分。它不纯。【参考方案3】:我的几点如下。
UI 状态和业务/后端状态在 redux 中耦合在一起。因此,对 ui 或业务状态的每次更新都会在 redux 存储中创建一个数据更新。 Xstate 将 UI 状态和后端状态解耦。 在 redux 中,所有节点都存在于根节点内。 Xstate 在独立的机器中分散和分发数据。 应用程序只能在已定义的状态之间转换。因此机器本身可以修复任何错误或错误。 内部状态由机器本身在 Xstate 中管理。 Redux 将新状态表示为标志。 渲染器竞争 - 将尽可能多的状态提升到机器中,如果需要,我们可以相对容易地切换渲染框架(例如从 react 到 vue)。 Contexts 提供了具体的类来向外界呈现一个单一的接口。【讨论】:
以上是关于redux 和状态机(例如 xstate)之间的实际区别是啥?的主要内容,如果未能解决你的问题,请参考以下文章