在工作空间,我的同事告诉我,我必须,而不是写这个
import store from './store.ts'
// Epic code
...
mergeMap(data => {
store.dispatch(someActionCreator(data))
return EMPTY
})
...
应该这样写
// Epic code
...
mergeMap(data => {
return of(someActionCreator(data))
})
...
我知道所有写在的中的动作RXJS操作符将自动封装在分派函数中并自动分派,但是为什么像第一个例子那样分派所有的动作是不好的呢?
是的,我们不会返回任何流$,但是如果这是序列中的最后一次迭代,我们真的需要返回这个流$而不是手动调度吗?
不引起"副作用"被认为是最佳实践。在大多数操作中。副作用可以描述为在"外部"某处修改/改变状态的语句。
对于dispatch
调用,您直接导致状态的突变,这可以被认为是副作用。
为什么应该避免副作用有很多观点。我可以举几个例子:
- 纯度:操作符应该总是对相同的输入产生相同的输出,这包括对外部状态的更改。通过保持操作符的纯粹性,可以对它们进行适当的单元测试,并且可以保证在操作符的所有使用中行为一致。
- 可重用性:操作符的设计应该使它们原则上可以在其他地方被提取和重用。这意味着它们应该没有外部依赖,比如直接在你的操作符中存储。
- 约定:操作符应被视为修改一个或多个传入数据流的函数集合。任何"reaction"对此流的结果操作应在"下标"中完成。这是一个有助于使可观察对象行为一致的约定。换句话说:当有人订阅你的Observable时,他们应该不会有副作用。在redux的例子中,那个"某人">
- 声明式范例:操作符应该主要描述输入和输出之间的关系,而不包括"指令";或者像"做这个,然后做那个"这样的语句。这是一种被认为可以减少错误的范例,因为它消除了对系统底层状态的依赖。
顺便说一下,整个操作符模式的起源是函数式编程,在函数式编程中,像您描述的这样的调用在技术上是不可能的。
所以我认为你的问题的答案主要是意见驱动的。从技术上讲,我相信它不会改变您的用例中的任何内容。此外,上述观点应该持保留态度,因为如果你订阅了mergeMap
中的HTTP API,你总是会在某些地方引起副作用。