乐闻世界logo
搜索文章和话题

为什么使用 redux-observable 而不是 redux- saga ?

7 个月前提问
3 个月前修改
浏览次数116

6个答案

1
2
3
4
5
6

当选择状态管理库的中间件时,Redux-Observable 和 Redux-Saga 都是强大的选择,它们各自有不同的优点。选择使用 Redux-Observable 的理由可能包括以下几点:

响应式编程与RxJS

Redux-Observable 基于 RxJS,这是一个响应式编程库,它可以让你使用 Observables 处理异步事件和基于流的编程。如果团队已经熟悉响应式编程范式,或者项目中已经在使用RxJS,那么使用 Redux-Observable 会更有意义,因为它可以让你利用已有的知识和代码库。

示例: 假如我们有一个需要处理多个不同数据流的复杂应用程序,比如实时股票价格更新、用户操作和网络请求等。使用 RxJS,我们可以创建一个统一的流来处理这些信息,并且可以很容易地通过各种操作符来合并、过滤、转换这些流。

操作符丰富

RxJS 提供了强大的操作符集合,这使得在复杂场景下处理异步操作变得更加灵活和强大。比如,可以使用 debounceTimethrottleTimeswitchMapmergeMapconcatMap 等操作符来进行节流、防抖、取消之前的请求等。

示例: 考虑一个自动完成的输入框,我们希望在用户输入时调用一个 API 来显示建议,但我们不希望在每次按键上都做这个调用,而是希望在输入稳定后进行。我们可以使用 debounceTime 操作符来实现这一点,它会等待一段时间直到没有新的输入,然后才执行 API 调用。

更紧密的集成

Redux-Observable 允许开发者以一种更紧密集成的方式将 action 创建者、异步流和 Redux store 结合起来。这样可以让你的 Epic(用于处理异步操作的函数)在不影响 UI 组件的情况下访问当前的 store 状态并且派发多个 action。

示例: 假设我们需要根据用户的一系列行为来触发不同的 action。例如,在用户登录成功后,我们可能需要获取用户的个人信息、加载用户的偏好设置等。在 Redux-Observable 中,我们可以在一个 Epic 中监听登录成功的 action,然后使用 RxJS 操作符链来处理这个复杂的流程。

流控制和错误处理

在 RxJS 中,流的概念和错误处理是一级公民。这意味着开发者可以以一种声明式的方式来管理流的生命周期和错误,这在某些应用场景下可能比 Redux-Saga 的 Generator 函数更方便。

示例: 想象一个情况,我们正在处理网络请求,并希望在请求失败时进行重试。RxJS 提供了 retryretryWhen 操作符,这让我们可以简单地实现这种复杂的逻辑。

总结

选择 Redux-Observable 的理由通常取决于开发团队对响应式编程的偏好,以及对 RxJS 的熟悉程度。如果开发者已经习惯于使用 RxJS,并且希望能够利用其提供的强大功能来处理复杂的异步或基于流的场景,那么 Redux-Observable 是一个非常合适的选择。相比之下,如果团队更熟悉传统的 JavaScript 和异步处理方式,Redux-Saga 可能会更符合他们的习惯。

2024年6月29日 12:07 回复

免责声明:我是 redux-observable 的作者之一,所以我很难做到 100% 公正。

我们目前没有提供任何 redux-observable 比 redux-saga 更好的理由,因为……事实并非如此。😆

tl;dr 两者都有优点和缺点。许多人会发现其中一个比另一个更直观,但如果您不了解 RxJS (redux-observable) 或生成器/“效果作为数据”(redux-saga),那么以不同的方式学习两者都会很复杂。

它们以极其相似的方式解决相同的问题,但存在一些根本性的差异,只有当您充分使用它们时,这些差异才会真正显现出来。

redux-observable 几乎将一切都推迟到惯用的 RxJS。所以如果你有 RxJS 知识(或获得它),学习和使用 redux-observable 是超级超级自然的。这也意味着这些知识可以转移到 redux 之外的其他事物上。如果您决定切换到 MobX,如果您决定切换到 Angular2,如果您决定切换到未来的热门 X,RxJS 很有可能可以帮助您。这是因为 RxJS 是一个通用的异步库,并且在很多方面本身就像一种编程语言——整个“反应式编程”范例。RxJS 自 2012 年起就存在,最初是作为 Rx.NET 的一个端口(几乎每种主要语言都有“端口”,它_很有用_)。

redux-saga 本身提供了基于时间的运算符,因此虽然您在此流程管理器风格中获得的有关生成器和处理副作用的知识是可以转移的,但实际的运算符和用法并未在任何其他主要库中使用。所以这有点不幸,但本身不应该成为破坏交易的因素。

它还使用“效果作为数据”(此处描述),一开始可能很难理解,但这意味着您的 redux-saga 代码本身并不实际执行副作用。相反,您使用的辅助函数会创建类似于任务的对象,这些任务代表执行副作用的意图,然后内部库会为您执行它。这使得测试变得非常容易,不需要模拟,并且对某些人来说非常有吸引力。然而,我个人发现这意味着你的单元测试重新实现了你的传奇的大部分逻辑——使得这些测试在我看来不是很有用(并不是每个人都同意这个观点)

人们经常问为什么我们不使用 redux-observable 做类似的事情:对我来说,它从根本上与正常的惯用 Rx 不兼容。在 Rx 中,我们使用类似的运算符.debounceTime()来封装去抖所需的逻辑,但这意味着如果我们想要制作一个实际上不执行去抖而是发出带有意图的任务对象的版本,那么您现在已经失去了Rx 的力量,因为你不能再仅仅链接运算符,因为它们将在该任务对象上进行操作,而不是操作的真实结果。这确实很难优雅地解释。它再次需要对 Rx 有深入的了解才能理解方法的不兼容性。如果你_真的_想要这样的东西,请查看redux-cycles,它使用 Cycle.js 并且主要有这些目标。我发现这对我来说需要太多仪式,但如果你感兴趣的话,我鼓励你尝试一下。

正如 ThorbenA 提到的,我并不回避承认 redux-saga 目前(2016 年 10 月 13 日)是 redux 复杂副作用管理领域的明显领导者。它起步较早,拥有更强大的社区。因此,使用事实上的标准比新来的标准更有吸引力。我认为可以肯定地说,如果您在没有先验知识的情况下使用其中任何一个,您就会感到困惑。我们都使用相当先进的概念,一旦你“掌握”了这些概念,复杂的副作用管理就会变得容易得多,但在那之前很多人都会遇到困难。

我能给出的最重要的建议是,在需要这些库之前不要引入它们。如果您只进行简单的 ajax 调用,则可能不需要它们。redux-thunk 学习起来非常简单,并且提供了足够的基础知识——但是异步越复杂,redux-thunk 就越难(甚至不可能)。但对于 redux-observable/saga 在很多方面来说,异步越复杂,它就越闪耀。在同一项目中将 redux-thunk 与其他方法之一(redux-observable/saga)一起使用也有很多优点!redux-thunk 用于常见的简单内容,然后仅使用 redux-observable/saga 来处理复杂的内容。这是保持生产力的好方法,所以你不会为了那些用 redux-thunk 来说微不足道的事情而与 redux-observable/saga 作斗争。

2024年6月29日 12:07 回复

我认为有些事情你需要考虑。

  1. 复杂
  2. 编码风格
  3. 学习曲线
  4. 可测试性

假设我们想从 API 获取用户

shell
// Redux-Saga import axios from 'axios' function* watchSaga(){ yield takeEvery('fetch_user', fetchUser) // waiting for action (fetch_user) } function* fetchUser(action){ try { yield put({type:'fetch_user_ing'}) const response = yield call(axios.get,'/api/users/1') yield put({type:'fetch_user_done',user:response.data}) } catch (error) { yield put({type:'fetch_user_error',error}) } } // Redux-Observable import axios from 'axios' const fetchUserEpic = action$ => action$ .ofType('fetch_user') .flatMap(()=> Observable.from(axios.get('/api/users/1')) // or use Observable.ajax .map(response=>({type:'fetch_user_done', user:response.data})) .catch(error => Observable.of({type:'fetch_user_error',error})) .startWith({type:'fetch_user_ing'}) )

另外,我写这篇文章是为了深入比较 Redux-saga 和 Redux-Observable 之间的差异。请查看此处的链接演示文稿

2024年6月29日 12:07 回复

我使用 Redux-Observable 而不是 Redux-Saga,因为我更喜欢使用 observables 而不是生成器。我将它与 RXJS 一起使用,这是一个用于处理数据流的强大库。可以把它想象成异步的 lodash。关于选择其中一个的任何缺点、陷阱和妥协,请看一下Jay Phelps 的回答

redux-saga 作为一个项目比 redux-observable 存在的时间更长,因此这无疑是一个主要卖点。您会发现更多文档、示例,并且可能有更好的社区可以获得支持。

相反的是,你在 redux-saga 中学习的运算符和 API 几乎不像学习 RxJS 那样可转移,而 RxJS 到处都在使用。redux-observable 内部超级超级超级简单,它实际上只是为您提供了一种使用 RxJS 的自然方式。因此,如果您了解 RxJS(或想要了解),那么它是非常合适的。

目前我对大多数人的建议是,如果您不得不问应该使用哪一个,那么您可能应该选择 redux-saga。

2024年6月29日 12:07 回复

Redux-Observable 是一个令人惊叹的库,我们在生产中使用它 1.5 年了,到目前为止没有任何问题,它完全可测试,并且可以轻松与任何框架集成。我们的并行套接字通道超载,唯一能避免冻结的就是 Redux-Observable

在这里我想提三点。

1. 复杂性和学习曲线

Redux-saga 在这里轻松击败了 redux-observable。如果你只需要一个简单的请求来完成授权,并且由于某些原因你不想使用 redux-thunk,你应该考虑使用 redux-saga,它更容易理解。

如果您事先没有 Observable 的知识,这对您来说会很痛苦,您的团队将为您提供指导:)

2. Observable 和 RxJS 能为我提供什么?

当谈到异步逻辑时,Observable 就是你的瑞士刀,Observable 几乎可以为你做所有事情。你永远不应该将它们与承诺或发电机进行比较,它的功能要强大得多,就像将擎天柱与雪佛兰进行比较一样。

那么 RxJS 呢?它就像 lodash.js,但对于异步逻辑,一旦你进入,你将永远不会切换到不同的东西。

3. 反应式扩展

只需检查此链接

http://reactivex.io/languages.html

反应式扩展适用于所有现代编程语言,它只是函数式编程的关键。

因此,明智地花时间学习 RxJS 并使用 redux-observable :)

2024年6月29日 12:07 回复

我很看重 Rx 所具有的跨语言和运行时的可移植性。即使您的应用程序不会改变语言,您的职业生涯也可能会改变。无论您自己如何衡量,都可以在学习中获得最大的影响力。它是通往 .Net LINQ 的绝佳网关。

2024年6月29日 12:07 回复

你的答案