Redux和RxJS,有何相似之处?


113

我知道Redux是Flux的一个更好的“实现”,或者说它是一种简化设计(应用程序状态管理)的重新设计。

我已经听说过很多关于反应式编程(RxJS)的知识,但是我还没有开始学习它。

所以我的问题是:这两种技术之间是否有任何交叉点(或任何共同点)还是互补的?...或完全不同?

Answers:


185

简而言之,它们是出于完全不同的目的而完全不同的库,但是是的,存在一些模糊的相似之处。

Redux是用于管理整个应用程序状态的工具。它通常用作UI的体系结构。可以将其视为Angular的替代(一半)。

RxJS是一个反应式编程库。它通常用作在JavaScript中完成异步任务的工具。可以将其视为Promises的替代方案。


响应式编程是一种从远处观察到数据变化的范例(工作和思考的方式)。数据不会远距离改变

这是远距离改变的例子:

// In the controller.js file
model.set('name', 'George');

模型被改变从控制器。

这是从远处观察到的示例:

// logger.js
store.subscribe(function (data) {
    console.log(data);
});

在记录器中,我们观察存储中发生的数据更改(从远处),并将其写入控制台。


Redux仅使用了Reactive范式:Store是反应式的。您不能远距离设置其内容。这就是为什么store.set()Redux中没有。商店从远处观察动作,并自行更改。并且商店允许其他人从远处观察其数据。

RxJS还使用了Reactive范式,但它不是体系结构,而是为您提供了基本的构建基块Observables,以完成这种“从远处观察”的模式。

总而言之,出于不同的目的,有截然不同的事物,但有一些共同点。


4
不,您不应该一起使用它们。人们已经使用Rx模拟Redux。快速的Google会为您找到示例。如果您想将Rx用于您的反应式UI,请查看Andre的框架Cycle.js。我最近一直在使用它,它很棒。API最近发生了很大变化,但是我相信他终于开始冻结部分内容。
Joel Dentici 2015年

17
根据官方的redux文档,“他们在一起工作很好。”
加尔奇

12
他们在一起做得很好!有一个Redux中间件,它使您有机会使用RxJS和Observables进行Redux操作。github.com/redux-observable/redux-observable另外,我写了一篇有关如何做的博客文章:robinwieruch.de/redux-observable-rxjs
Robin Wieruch

1
Redux范例帮助使我的Android项目代码库更具反应性。我们的数据流来自按钮和其他字段以与RxJava一起更新状态,从而增强了我们的可读性和性能。这些库绝对可以很好地配合使用,并且它们的好处与语言无关。
肯尼·沃登

他们工作的伟大在一起的,但在实践中反应能为你做什么终极版会做-你同步组件模型的状态,所以往往没有多大意义,同时使用
菲利普Sobczak

32

他们是完全不同的东西。

RxJS可用于进行响应式编程,它是一个非常全面的库,具有250多个运算符。

github库中描述了Redux,“ Redux是JavaScript应用程序的可预测状态容器”。

Redux只是处理应用程序状态的工具。但是相比之下,您可以仅使用RxJS来构建完整的应用程序。

希望这可以帮助 :)


3
您的答案也很好@cmdv。我写我的书时没看过。
安德烈·斯塔尔茨(AndréStaltz)2015年

4

Redux只是一个状态管理库,带有定义明确的更新操作标准。只要遵守标准,就可以使数据流保持理智并易于推理。它还带来了使用中间件和存储增强器增强数据流的能力。

RxJS是用于反应式编程的工具包。实际上,您可以将应用程序中发生的所有事情视为流。RxJS提供了非常丰富的工具集来管理这些流。

RxJS和Redux拦截在哪里?在redux中,您可以使用操作来更新状态,显然这些操作可以视为流。使用像redux-observable这样的中间件(您不必这样做),您可以以被动方式实现所谓的“业务逻辑”。另一件事是,您可以从redux存储中创建一个可观察对象,这有时可能比使用增强器容易。


2

简而言之:

Redux:受Flux启发的用于状态管理的库。

RxJS:这是基于反应式编程原理的另一个Javascript库,用于处理“流”(Observables等)[阅读有关反应式编程以了解流概念的信息]。


1

我只是想添加一些与Redux启发的RxJS代码时的实际差异。

我将每种操作类型映射到Subject实例。每个有状态组件都将具有一个Subject,然后将其映射到一个reducer函数。所有reducer流都与合并,merge然后scan输出状态。默认值设置startWithscan。我曾经使用publishReplay(1)过状态,但以后可能会删除它。

react pure render函数将仅用于通过发送所有生产者/对象来产生事件数据的地方。

如果您有子组件,则需要描述这些状态如何组合到您的子组件中。combineLatest可能是一个很好的起点。

实施方面的显着差异:

  • 没有中间件,只有rxjs运算符。我认为这是最大的力量和弱点。您仍然可以借用概念,但是我发现很难从姐妹社区(例如redux和cycle.js)获得帮助,因为它是另一种自定义解决方案。这就是为什么我需要在本文中写“ I”而不是“ we”。

  • 动作类型没有开关/大小写或字符串。您可以采用更加动态的方式来分离动作。

  • rxjs可以在其他地方用作工具,并且不包含在状态管理中。

  • 生产者数量少于动作类型(?)。我对此不确定,但是您可以在侦听子组件的父组件中有很多反应。这意味着更少的命令性代码和更少的复杂性。

  • 您拥有解决方案。无需框架。好和坏。您将最终以任何方式编写自己的框架。

  • 它是分形的,您可以轻松地从子树或应用程序状态树的多个部分订阅更改。

    • 猜想像redux-obseravble那样做史诗有多容易?真的很容易。

我还在研究更大的好处,其中子组件被描述为流。这意味着我们不必在化简器中包含父状态和子状态,因为我们可以(“公正”)基于组件结构来递归组合状态。

我还考虑跳过反应,并采取镇压措施或其他措施,直到React更好地处理反应状态。我们为什么要向上建立我们的国家,以便再次通过道具分解它?因此,我将尝试使用Snabbdom制作此模式的版本2。

这是一个更高级的小片段,其中state.ts文件用于构建状态流。这是ajax形式的组件的状态,该状态获取具有验证规则和CSS样式的字段(输入)对象。在此文件中,我们仅使用字段名称(对象键)将所有子状态组合为表单状态。

export default function create({
  Observable,
  ajaxInputs
}) {
  const fieldStreams = Object.keys(ajaxInputs)
  .map(function onMap(fieldName) {
    return ajaxInputs[fieldName].state.stream
    .map(function onMap(stateData) {
      return {stateData, fieldName}
    })
  })

  const stateStream = Observable.combineLatest(...fieldStreams)
  .map(function onMap(fieldStreamDataArray) {
    return fieldStreamDataArray.reduce(function onReduce(acc, fieldStreamData) {
    acc[fieldStreamData.fieldName] = fieldStreamData.stateData
    return acc
  }, {})
  })

  return {
    stream: stateStream
  }
}

尽管代码可能不会孤立地讲很多,但它显示了如何向上构建状态以及如何轻松生成动态事件。需要付出的代价是您需要了解不同的代码风格。我喜欢为此付出代价。


一年后,我才找到您的答案,并认为它仍然有效!我做了类似的事情,并同意您的所有观点。但是无论如何,还是有一个问题:您今天还是这么想,还是此后继续前进?
Xceno

1
我需要修改对Redux中的switch / case和action类型的批评。我仍然以相同的方式进行编码,但是尝试着使它在服务器端正常工作。当涉及到React代码时,我设法做了一个小工具,可以帮助创建reducer / updaters。所以我仍然在做同样的事情,但是更加精致。最大的变化是,我让每个叶节点在componentDidMount上订阅流,并在componentDidUnmount上取消订阅。我也想获得一个在前端和后端都可以使用的反应式服务层。在那里取得进展。
马库斯·罗德尔(MarcusRådell),
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.