我使用过Redux-Saga。用它编写的代码到目前为止很容易理解,除了JS生成器功能不时弄乱我的脑袋。根据我的理解,Redux-Observable可以实现处理副作用但不使用生成器功能的类似工作。
然而,来自Redux-Observable的文档并没有提供很多关于它为什么优于Redux-Saga的观点。我想知道是否使用生成器函数是使用Redux-Observable的唯一好处。使用Redux-Observable而不是Redux-Saga会有什么缺点,不足或妥协?提前谢谢。
答案 0 :(得分:196)
免责声明:我是redux-observable的作者之一,因此我很难100%公正。
我们目前没有提供任何理由,redux-observable比redux-saga更好,因为......它不是。
他们以非常相似的方式解决同样的问题,但有一些基本的差异,只有在你足够使用它们后才会变得非常明显。
redux-observable几乎将所有东西都推迟到惯用的RxJS。因此,如果你有RxJS知识(或获得它),学习和使用redux-observable是超级自然的。这也意味着这种知识可以转移到除redux之外的其他事物。如果您决定切换到MobX,如果您决定切换到Angular2,如果您决定切换到未来的热点X,那么RxJS可以帮助您的机会非常好。这是因为RxJS是一个通用的异步库,在很多方面就像一个编程语言本身 - 整个"反应式编程"范例。 RxJS自2012年起就存在并开始作为Rx.NET的一个端口(几乎所有主要语言都有#34; ports"它有用的)。
redux-saga本身提供了基于时间的运算符,因此,虽然您在此流程管理器样式中获取的有关生成器和处理副作用的知识是可转移的,但实际的运算符和用法并未在任何其他主要库中使用。这有点不幸,但当然不应该是一个交易破坏者。
它还使用"效果作为数据" (described here),一开始可能很难缠头,但这意味着你的redux-saga代码实际上并没有实现副作用。相反,您使用的辅助函数创建的对象类似于表示执行副作用的意图的任务,然后内部库为您执行。这使得测试非常简单,无需嘲笑,对某些人来说非常有吸引力。但是,我个人已经发现这意味着你的单元测试重新实现了你的大部分故事 - 使这些测试不是很有用的IMO(这个观点并不是每个人共享的)
人们经常会问为什么我们不能用redux-observable做类似的事情:对我而言,它与普通惯用的Rx根本不相容。在Rx中,我们使用.debounceTime()
之类的运算符来封装去抖动所需的逻辑,但这意味着如果我们想要制作一个没有实际执行去抖动的版本,而是使用intent发出任务对象,你现在已经失去了Rx的力量,因为你不能仅仅依赖链接操作员,因为他们正在操作该任务对象,而不是操作的真实结果。这很难优雅地解释。它还需要对Rx有深入的了解才能理解方法的不兼容性。如果您确实想要这样的东西,请查看使用cycle.js的redux-cycles,并且大多数都有这些目标。我发现它需要太多的仪式来满足我的口味,但如果你感兴趣,我鼓励你给它一个旋转。
正如ThorbenA所提到的,我不会回避承认redux-saga目前(10/13/16)是redux复杂副作用管理的明显领导者。它起步较早,拥有更强大的社区。因此,使用事实上的标准对于街区的新孩子来说,有很大的吸引力。我认为如果您在没有事先知识的情况下使用它们,可以说是安全的,您可能会感到困惑。我们都使用了相当先进的概念,一旦你得到了#34;就会使复杂的副作用管理变得容易得多,但在此之前很多人都会绊倒。
我能给出的最重要的建议是不要在需要之前引入这些库中的任何一个。如果您只是进行简单的ajax通话,那么您可能并不需要它们。 redux-thunk简单易学,为基础提供了足够的东西 - 但异步越复杂,对于redux-thunk来说就越难(甚至不可能)。但是对于redux-observable / saga来说,它在很多方面都闪耀得越多,异步就越复杂。在同一个项目中使用redux-thunk和其他一个(redux-observable / saga)也有很多优点! redux-thunk用于常见的简单内容,然后仅使用redux-observable / saga进行复杂的操作。这是一种保持工作效率的好方法,所以你不会因为使用redux-thunk而无法使用redux-observable / saga。
答案 1 :(得分:47)
我认为有些事情你需要考虑。
让我们说我们想要从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之间的差异。查看this link here或presentation。
答案 2 :(得分:18)
我在Redux-Saga上使用Redux-Observable,因为更喜欢使用observable而不是生成器。我将它与RXJS一起使用,RXJS是一个用于处理数据流的强大库。把它想象成为异步的lodash。关于任何缺点,在选择其中一个方面存在问题和妥协,请看看Jay Phelps的this answer:
作为一个项目,redux-saga比redux-observable存在的时间更长,这无疑是一个主要的卖点。您将找到更多文档,示例,并且可能有更好的社区来获得支持。计数器是你在redux-saga中学到的运算符和API几乎不像学习RxJS那样可以转移,RxJS遍布各地。 redux-observable是超级超级简单的内部,它真的只是给你一个自然的方式来使用RxJS。所以如果你知道RxJS(或者想要),那就非常自然了。
我对大多数人的建议是,如果你不得不问你应该使用哪一个,你可能应该选择redux-saga。
答案 3 :(得分:6)
我重视Rx所具有的语言和运行时间的可转移性。即使您的应用不会改变语言,您的职业生涯也可能如此。在您的学习中获得最佳的杠杆作用,无论您为自己规模如此。它特别适合.Net LINQ。
答案 4 :(得分:4)
Redux-Observable是一个了不起的图书馆,我们在生产中使用它已经有1.5年没有任何问题,它完全可以测试,可以很容易地与任何框架集成。我们正在拥有极度超载的并行套接字通道,唯一可以让我们免于冻结的是Redux-Observable
我想在此提及3分。
<强> 1。复杂性和学习曲线
Redux-saga在这里轻松击败redux-observable。如果您只需要一个简单的请求来完成授权而且您不想因为某些原因而使用redux-thunk,那么您应该考虑使用redux-saga,它更容易理解。
如果您不具备Observable的先验知识,那将对您造成痛苦,您的团队将为您提供帮助:)
<强> 2。 Observable和RxJS能为我提供什么?
当谈到异步逻辑Observable是你的瑞士刀时,Observable可以为你做几乎所有事情。你永远不应该将它们与承诺或发电机进行比较,它的功能要强得多,就像比较擎天柱和雪佛兰一样。
那么RxJS呢?它就像lodash.js,但对于异步逻辑,一旦你进入你就永远不会切换到不同的东西。
第3。反应性扩展
只需查看此链接
即可针对所有现代编程语言实现了反应式扩展,它只是函数式编程的关键。
所以花时间明智地学习RxJS并使用redux-observable:)
答案 5 :(得分:1)
由于这里有很多关于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。
答案 6 :(得分:0)
如果您使用Typescript编写应用程序,建议您检查typeless。 它受Redux-Observable的启发,也依赖于RxJS,但是构建应用程序的整个生态系统都是如此。
redux-observable / redux-saga的最大缺点是缺乏指导原则。没有关于如何减少负载减少器,saga或史诗的官方指南。扩展更大的应用程序时,代码拆分至关重要。 延迟加载的自定义解决方案通常无法与HMR一起使用,从而导致不良的开发人员体验。