为什么我们需要 return 一个流而不是直接派发一个值?

Why we need to return a stream instead of direct dispatch a value?

在工作区,我的同事告诉我,我必须而不是写这个

import store from './store.ts'

// Epic code
...
mergeMap(data => {
    store.dispatch(someActionCreator(data))
    return EMPTY
})
...

应该这样写

// Epic code
...
mergeMap(data => {
    return of(someActionCreator(data))
})
...

我知道写在of rxjs operator 中的所有动作都会自动包装在调度函数中并自动调度,但是为什么像在第一个例子?

是的,我们不会 return 任何流 $,但如果它是序列中的最后一次迭代,我们真的需要 return 这个流 $ 而不是手动调度吗?

在大多数运算符中不引起“副作用”被认为是最佳实践。副作用可以描述为在 Operator 链“外部”某处修改/改变状态的语句。

调用dispatch直接导致state的突变,也算是副作用

为什么应该避免副作用有很多观点。我可以举几个:

  • 纯粹性:运算符应始终为相同的输入产生相同的输出,其中包括对外部状态的更改。通过保持运算符的纯净,可以对它们进行适当的单元测试,并且您可以保证在运算符的所有用法中行为一致。
  • 可重用性:运算符的设计原则上应确保它们可以在其他地方提取和重用。这意味着它们应该没有外部依赖项,例如直接在您的运营商中的商店。
  • 约定:运算符应被视为一组函数,用于修改一个或多个传入数据流。对这个流操作结果的任何“反应”都应该在“订阅”中完成。这是一个有助于使 Observables 行为一致的约定。换句话说:当有人订阅你的 Observable 时,他们应该不会有任何副作用。在 redux 的情况下,那个“某人”就是框架。
  • 声明式范式:操作符应该主要描述输入和输出之间的关系,而不包括“指令”或语句,例如“做这个,然后做那个”。这是一种被认为可以减少整体错误的范例,因为它消除了对系统底层状态的依赖。

顺便说一下,整个运算符模式的起源是函数式编程,从技术上讲,您所描述的这样的调用是不可能的。

所以我认为你的问题的答案主要是意见驱动的。从技术上讲,我相信它不会改变您的用例中的任何内容。此外,上面提出的观点应该有所保留,因为如果您订阅例如,您总会在某处造成副作用。 mergeMap.

中的 HTTP API