为什么在Redux-Saga上使用Redux-Observable?

Iva*_*ang 122 javascript reactive-programming redux redux-saga redux-observable

我使用过Redux-Saga.用它编写的代码到目前为止很容易理解,除了JS生成器功能不时弄乱我的脑袋.根据我的理解,Redux-Observable可以实现处理副作用但不使用生成器功能的类似工作.

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

jay*_*lps 217

免责声明:我是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代码实际上并没有执行副作用.相反,您使用的辅助函数创建的对象类似于表示执行副作用的意图的任务,然后内部库为您执行.这使得测试非常简单,无需嘲笑,对某些人来说非常有吸引力.但是,我个人已经发现这意味着你的单元测试重新实现了你的saga的大部分逻辑 - 使这些测试不是很有用的IMO(这个观点不是每个人都有的)

人们经常会问为什么我们不会使用redux-observable做类似的事情:对我而言,它与普通的惯用Rx根本不相容.在Rx中,我们使用这样的运算符.debounceTime()封装去抖动所需的逻辑,但是这意味着如果我们想要制作一个实际上不执行去抖动的版本而是用意图发出任务对象,那么你现在已经失去了Rx的强大之处在于你不能仅仅依赖链接操作符,因为它们正在操作该任务对象,而不是操作的真实结果.这很难优雅地解释.它还需要对Rx有深入的了解才能理解方法的不兼容性.如果你真的想要这样的东西,请查看使用cycle.js的redux-cycles,并且大多数都有这些目标.我发现它需要太多的仪式来满足我的口味,但我鼓励你如果感兴趣的话就给它一个旋转.

正如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作斗争.

  • 刚刚看了[您的讲话](https://www.youtube.com/watch?v=AslncyG8whg)(声音很响!),然后立即按⌘+ T +“ redux-saga vs redux-observable”。我已经使用redux-saga很长时间了(尤其是在React Native中),但是看完您的演讲和这篇文章后,我可以看到redux-obs的一些用例(对我而言)。实际上会更合适。您关于`debounceTime()`的示例对一种非常通用的逻辑“失去”控制权的举动对我来说是成功的。感谢您的解释。 (3认同)
  • 刚才也看到了谈话,并做了更多的谷歌搜索。好东西@jayphelps,谢谢分享。我特别喜欢您关于将redux-thunk与redux-observable / saga结合使用的评论。这很有意义,为什么在不必要时使简单的AJAX请求过于复杂。话虽这么说,但为了保持一致和保持人们的一致性,有话要说。再次感谢! (3认同)

Way*_*hiu 56

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

  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'})
        )
Run Code Online (Sandbox Code Playgroud)

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

  • @jamesemanon我假设他没有使用fetch,因为fetch API还没有取消选项.(更多内容:https://github.com/whatwg/fetch/issues/27) (4认同)
  • 这个链接的并排比较很好,谢谢 (2认同)

Tho*_*enA 18

我使用Redux-Observable而不是Redux-Saga,因为我更喜欢使用可观察量而不是生成器.我将它与RXJS一起使用,RXJS是一个用于处理数据流的强大库.把它想象成为异步的lodash.在任何缺点方面,在选择其中一个方面存在问题和妥协,请看看Jay Phelps的答案:

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

计数器是你在redux-saga中学到的运算符和API几乎不像学习RxJS那样可以转移,RxJS遍布整个地方.redux-observable是超级超级简单的内部,它真的只是给你一个自然的方式来使用RxJS.因此,如果您了解RxJS(或想要),那么它非常自然.

我对大多数人的建议是,如果你不得不问你应该使用哪一个,你可能应该选择redux-saga.


Dea*_*ffe 6

我重视Rx具有的语言和运行时的可转移性.即使您的应用不会改变语言,您的职业生涯也可能如此.在您的学习中获得最佳的杠杆作用,无论您为自己规模如此.它特别适合.Net LINQ.

  • 明智的选择,尽管生成器也与语言无关。 (3认同)

Den*_*lka 6

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

我想在这里提三点。

1.复杂性和学习曲线

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

如果您不具备Observable的先验知识,那将是您的痛苦,您的团队将为您提供培训

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

当谈到异步逻辑时,Observable是您的瑞士刀,实际上,Observable可以为您做几乎所有的事情。您永远不要将它们与功能更强大的Promise或Generator进行比较,就像将Optimus Prime与Chevrolet进行比较一样。

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

3.反应性扩展

只需检查此链接

http://reactivex.io/languages.html

对所有现代编程语言都实现了响应式扩展,这只是您进行函数式编程的关键。

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


小智 5

由于这里有一大堆关于 redux-observable 的讨论,我想我会给出论点的传奇方面。我不使用 redux-observable 或 RxJS,所以我不能并排比较,但我使用了传奇效果很好。

就其价值而言,我正在 Web 应用程序的生产中使用 sagas。

Sagas vs. Thunk

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

Sagas 的学习曲线

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

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

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

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

结论

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

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