我用过Redux-Saga。到目前为止,用它编写的代码很容易推理,除了JS生成器功能不时使我头晕。据我了解,Redux-Observable可以完成类似的处理副作用的工作,但无需使用生成器功能。
但是,来自Redux-Observable的文档并没有提供很多关于为什么它比Redux-Saga优越的意见。我想知道是否不使用生成器功能是使用Redux-Observable的唯一好处。使用Redux-Observable而不是Redux-Saga可能带来什么弊端,陷阱或妥协?提前致谢。
我用过Redux-Saga。到目前为止,用它编写的代码很容易推理,除了JS生成器功能不时使我头晕。据我了解,Redux-Observable可以完成类似的处理副作用的工作,但无需使用生成器功能。
但是,来自Redux-Observable的文档并没有提供很多关于为什么它比Redux-Saga优越的意见。我想知道是否不使用生成器功能是使用Redux-Observable的唯一好处。使用Redux-Observable而不是Redux-Saga可能带来什么弊端,陷阱或妥协?提前致谢。
Answers:
免责声明:我是redux-observable的作者之一,因此很难做到100%公正。
我们目前没有提供任何理由说明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目前(16/13/16)是redux复杂副作用管理的明确领导者。它是较早开始的,拥有更强大的社区。因此,将事实标准用于新来的孩子有很多吸引力。我认为可以肯定地说,如果您在没有先验知识的情况下使用这两种方法,那将会有些混乱。我们俩都使用相当高级的概念,一旦您“了解”,复杂的副作用管理就容易多了,但是直到那时,仍然有很多绊脚石。
我能提供的最重要的建议是不要在需要它们之前引入任何一个这些库。如果您仅进行简单的ajax调用,则可能不需要它们。redux-thunk愚蠢易学,并且提供了足够的基础知识-但是异步越复杂,redux-thunk就会变得越难(甚至不可能)。但是对于redux-observable / saga而言,它在异步方面越复杂,它的作用就越多。在同一项目中将redux-thunk与其他一个(redux-observable / saga)一起使用也有很多优点!将redux-thunk用于您的普通简单内容,然后仅将redux-observable / saga用于复杂的内容。这是保持生产力的好方法,因此您不必为redux-observable / saga争夺那些与redux-thunk无关紧要的东西。
我认为您需要考虑一些事项。
假设我们要从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之间的差异。在此处或演示文稿中查看此链接。
我在Redux-Saga上使用Redux-Observable,因为相对于生成器,它更喜欢使用Observable。我将它与RXJS一起使用,它是一个功能强大的库,用于处理数据流。可以将其视为lodash进行异步处理。关于任何缺点,选择方面的陷阱和折衷,请看一下Jay Phelps的回答:
redux-saga作为一个项目存在的时间比redux-observable更长,因此这肯定是主要卖点。您会发现更多文档,示例,并且可能拥有更好的社区来获得支持。
与此相反的是,您在redux-saga中学习的运算符和API几乎不像在各处使用RxJS那样可移植。redux-observable在内部是超级超级超级简单,实际上只是为您提供了一种自然的方式来使用RxJS。因此,如果您了解RxJS(或想要了解),那是非常自然的选择。
目前,我对大多数人的建议是,如果您不得不问应该使用哪一个,则可能应该选择redux-saga。
Redux-Observable是一个了不起的库,我们在生产环境中使用它已有1.5年之久,到目前为止没有任何问题,它可以完美测试,并且可以轻松地与任何框架集成。我们的并行套接字通道极度过载,唯一使我们免于冻结的是Redux-Observable
我想在这里提三点。
1.复杂性和学习曲线
Redux传奇轻松击败了redux-observable。如果您只需要一个简单的请求就可以完成授权,并且由于某些原因而不想使用redux-thunk,则应该考虑使用redux-saga,它更容易理解。
如果您不具备Observable的先验知识,那将是您的痛苦,您的团队将为您提供培训:)
2. Observable和RxJS能为我提供什么?
当涉及到异步逻辑时,Observable是您的瑞士刀,实际上,Observable可以为您做几乎所有的事情。您永远不要将它们与功能强大得多的Promise或Generator进行比较,就像将Optimus Prime与Chevrolet进行比较一样。
那RxJS呢?它就像lodash.js,但是对于异步逻辑,一旦您进入就永远不会切换到其他东西。
3.反应性扩展
只需检查此链接
对所有现代编程语言都实现了响应式扩展,这只是您进行函数式编程的关键。
因此,花点时间明智地学习RxJS并使用redux-observable :)
我重视Rx跨语言和运行时的可移植性。即使您的应用程序不会更改语言,您的职业生涯也可能会改变。在学习中获得最大的影响,但是您可以自己调整大小。特别是通往.Net LINQ的绝佳门户。
既然这里有很多关于redux的演讲,我以为我会提出异议。我不使用redux-observable或RxJS,因此无法进行并行比较,但是我使用sagas效果很好。
对于它的价值,我在Web应用程序的生产中使用了Sagas。
佐贺胜出。我不喜欢笨拙的动作创作者如何运用逻辑。连续进行一些请求也很麻烦。我短暂地看了看这个工作可以观察到的redux,但是选择了Sagas。
了解什么是发电机以及为什么它们很重要是了解萨加斯的关键。但是我要强调的是,您不需要内外都知道生成器。您只需要知道您正在使用yield语句传递控制权,并且在您的异步代码解析后,传奇故事就会传递回控制权。在此之后,不难理解传奇中发生了什么。
核心的传奇方法是(以我的经验):
call
-调用任何代码并获取返回值。支持承诺。异步处理和Sagas之间的巨大协同作用。select
-呼叫选择器。这一点非常出色。选择器是redux的核心,并且100%支持!put
-又名dispatch
动作。实际上,您可以分派任意数量的物品!还有其他功能,但是如果您能熟练掌握这三个功能,那么您将处于真正的优势。
我选择sagas的原因是易于使用。redux-observable看起来像一个挑战。我对Sagas感到100%满意。比我预期的还要快乐。
以我的经验,萨加斯人比笨拙的人更好,并且相对容易理解。Rx并不是每个人的茶。如果您不是来自该生态系统和/或将来不打算使用Rx,我将强烈认为sagas而不是redux-observable。
如果你写的打字稿您的应用程序,我建议你检查无类型。它受Redux-Observable的启发,也依赖于RxJS,但是有用于构建应用程序的整个生态系统。
redux-observable / redux-saga的最大缺点是缺乏指导原则。没有关于如何减少负载减少器,saga或史诗的官方指南。扩展更大的应用程序时,代码拆分至关重要。延迟加载的自定义解决方案通常无法与HMR一起使用,从而导致不良的开发人员体验。