免责声明:我是 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 自己提供了基于时间的运算符,因此虽然您在这种流程管理器样式中获得的有关生成器和处理副作用的知识是可以转移的,但实际的运算符和用法并未在任何其他主要库中使用。所以这有点不幸,但它本身当然不应该破坏交易。
它还使用“作为数据的效果”(described here),一开始您可能难以理解,但这意味着您的 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 抗争。