147

我用过Redux-Saga。到目前为止,用它编写的代码很容易推理,除了 JS 生成器函数不时让我头疼。据我了解,Redux-Observable可以实现类似的处理副作用但不使用生成器函数的工作。

然而,来自 Redux-Observable 的文档并没有提供很多关于为什么它优于 Redux-Saga 的意见。我想知道不使用生成器函数是否是使用 Redux-Observable 的唯一好处。使用 Redux-Observable 而不是 Redux-Saga 可能有什么缺点、问题或妥协?提前致谢。

4

7 回答 7

263

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

我们目前没有提供任何理由 redux-observable 比 redux-saga 更好,因为......它不是。

tl;博士两者都有优点和缺点。许多人会发现其中一个比另一个更直观,但是如果您不了解 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 代码本身实际上并没有执行副作用。相反,您使用的辅助函数会创建类似于任务的对象,这些任务表示执行副作用的意图,然后内部库会为您执行它。这使得测试变得非常容易,无需模拟,并且对某些人非常有吸引力。但是,我个人发现这意味着您的单元测试重新实现了您传奇的大部分逻辑 - 使这些测试不是很有用 IMO(这种观点并非所有人都同意)

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

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

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

于 2016-10-13T17:51:54.927 回答
68

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

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

假设我们想从 API 获取用户

// 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 之间的差异。在此处查看此链接演示文稿

于 2017-01-13T04:09:29.313 回答
25

我使用 Redux-Observable 而不是 Redux-Saga,因为我更喜欢使用 observables 而不是生成器。我将它与 RXJS 一起使用,RXJS 是一个用于处理数据流的强大库。把它想象成异步的 lodash。就选择一个而不是另一个的任何缺点、陷阱和妥协而言,看看杰伊菲尔普斯的这个答案

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

反之,你在 redux-saga 中学习的操作符和 API 并不像学习 RxJS 那样可移植,RxJS 到处都在使用。redux-observable 内部超级超级超级简单,它实际上只是为您提供了一种使用 RxJS 的自然方式。因此,如果您了解 RxJS(或想了解),这是非常自然的选择。

目前我对大多数人的建议是,如果你必须问应该使用哪一个,你可能应该选择 redux-saga。

于 2016-10-13T13:35:26.783 回答
15

Redux-Observable 是一个了不起的库,我们在生产环境中使用了 1.5 年,到目前为止没有任何问题,它完全可测试并且可以轻松地与任何框架集成。我们有极度超载的并行套接字通道,唯一让我们免于冻结的是 Redux-Observable

我有 3 点想在这里提一下。

1. 复杂性和学习曲线

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

如果您没有 Observable 的先验知识,那对您来说会很痛苦,您的团队会为您提供课程:)

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

当谈到异步逻辑时,Observable 是你的瑞士刀,Observable 几乎可以为你做所有事情。你永远不应该将它们与更强大的 Promise 或生成器进行比较,就像将 Optimus Prime 与雪佛兰进行比较一样。

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

3. 反应式扩展

只需检查此链接

http://reactivex.io/languages.html

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

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

于 2018-01-25T21:37:00.703 回答
10

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

于 2017-04-20T03:11:19.540 回答
6

由于这里有一大堆可观察到 redux 的谈话,我想我会给出论点的传奇方面。我不使用 redux-observable 或 RxJS,所以我无法进行并排比较,但我使用 sagas 效果很好。

对于它的价值,我在 Web 应用程序的生产中使用 saga。

Sagas vs. Thunk

佐贺胜出。我不喜欢 thunk 如何在我的动作创建者中添加逻辑。这也使得连续执行一些请求很麻烦。我简要地查看了这项工作的 redux-observable,但最终选择了 Sagas。

Sagas 的学习曲线

了解什么是生成器以及它们为何如此重要是了解 sagas 的关键。但我要强调的是,你不需要了解发电机的里里外外。您只需要知道您正在使用 yield 语句传递控制权,并且 saga 将在您的异步代码解析后将控制权传递回。在那之后,不难理解传奇中发生了什么。

核心传奇方法是(根据我的经验):

  • call- 调用任意位代码并获取返回值。支持承诺。异步处理和 sagas 之间的巨大协同作用。
  • select- 调用选择器。这一点相当精彩。选择器是 redux 的核心,并且 100% 支持它们!
  • put- 也就是dispatch一个动作。事实上,你想发送多少就发送多少!

还有其他功能,但是如果您能掌握这三个功能,您将处于非常好的位置。

结论

我选择 sagas 的原因是易于使用。redux-observable 看起来像是一个挑战。我对传奇百分百满意。比我想象的还要开心。

根据我的经验,Sagas (方式)比 thunk 好,并且相对容易理解。Rx 不是每个人的一杯茶。如果你不是来自那个生态系统和/或不打算在未来使用 Rx,我会强烈考虑 sagas 而不是 redux-observable。

于 2019-02-05T19:19:33.257 回答
2

如果您使用 Typescript 编写应用程序,我建议检查typeless。它受到 Redux-Observable 的启发,也依赖于 RxJS,但有整个生态系统来构建应用程序。

redux-observable/redux-saga 的最大缺点是缺乏指导方针。没有关于如何延迟加载减速器、sagas 或史诗的官方指南。扩展更大的应用程序时,代码拆分至关重要。延迟加载的自定义解决方案通常不适用于 HMR,从而导致开发人员体验不佳。

无类型优点:

  1. 为 TypeScript 设计
    所有 API 都是为 typescript 和类型安全而设计的:
    • Typescript 将提高您的工作效率,而不是减慢您的速度。
    • 只需要必要的注释:状态、动作参数。
    • 没有类型转换。一切都是自动推断的。95% 的代码看起来像纯 JavaScript。
    • 没有 RootAction、RootEpic、RootState 或其他辅助类型。
  2. 提供所有构建块
    • 无类型包括构建中型或企业级应用程序的所有内容。
    • 您不需要依赖多个小型库。
  3. 模块化
    • 适当的模块化对于构建可扩展的应用程序至关重要。
    • 无需为史诗、reducers、类型等创建根文件。创建新模块后,您可以从任何地方附加它。类似于标准的 React 组件。
  4. 自以为是
    • 所有常见的用例和问题都默认解决。无需过度思考如何解决琐碎的问题。
    • 提供了所有建议和最佳实践!

查看https://typeless.js.org/

于 2019-10-06T05:43:19.173 回答