在工作区,我的同事告诉我,我必须这样做,而不是写这个
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 运算符编写的操作都会自动包装在调度函数中并自动调度,但为什么像第一个示例中那样调度所有操作是不好的呢?
是的,我们不会返回任何stream$,但是如果它是序列中的最后一次迭代,我们真的需要返回这个stream$而不是手动调度吗?
最佳答案
在大多数运算符(operator)中,不引起“副作用”被认为是最佳实践。副作用可以描述为修改/改变 Operator 链“外部”某处状态的语句。
通过 dispatch
调用,您直接导致状态发生变化,这可以被视为副作用。
为什么应该避免副作用有很多观点。我可以举几个:
- 纯粹性:运算符应始终为相同的输入生成相同的输出,其中包括外部状态的更改。通过保持运算符的纯净,可以对它们进行适当的单元测试,并且您可以保证运算符的所有用法中行为的一致性。
- 可重用性:原则上,运算符的设计应确保它们可以在其他地方提取和重用。这意味着它们不应该有外部依赖项,例如直接在您的运算符(operator)中进行存储。
- 约定:运算符应被视为修改一个或多个传入数据流的函数的集合。对此流操作的结果的任何“ react ”都应该在“订阅”中完成。这是一个有助于使 Observable 行为一致的约定。换句话说:当有人订阅你的 Observable 时,他们应该不会有任何副作用。就 redux 而言,“某人”就是框架。
- 声明式范式:运算符应主要描述输入和输出之间的关系,而不包含“指令”或语句,例如“这样做,然后那样做”。这是一种被认为可以减少总体错误的范例,因为它消除了对系统底层状态的依赖。
顺便说一句,整个运算符模式的起源是函数式编程,其中您所描述的调用在技术上是不可能的。
所以我认为你问题的答案主要是观点驱动的。从技术上讲,我相信它不会改变您的用例中的任何内容。另外,上面提出的观点应该持保留态度,因为如果您订阅例如,您总是会在某个地方造成副作用。 mergeMap
中的 HTTP API。
关于javascript - 为什么我们需要返回一个流而不是直接调度一个值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69646507/