这是我们升级到版本后在我们的应用程序中遇到的一个问题,1.x
他们引入了在当前堆栈完成后分派epic执行的排队操作(https://github.com/redux-observable/redux-observable/pull /493)。
想象一个动作 ( INIT_STUFF
),它有一个史诗,它返回一个动作列表 ( INIT_A
, INIT_B
, 按照这个顺序)。这些行动中的每一个都有自己的史诗。他们在那里做一些事情并返回一个修改商店的动作。
在以前版本的 redux-observable 中,epic forINIT_B
可能依赖于epic forINIT_A
已完成执行并对 store 进行更改的事实。然后这个史诗可以使用更新的商店。
在最新版本中,史诗的INIT_A
和INIT_B
都按各自的顺序执行,但它们返回的操作(修改存储)被推迟到最后一个史诗完成。这意味着史诗 forINIT_B
无法访问由INIT_A
.
这是我所说的简单实现:https : //redux-observable-playground-ip3qfb.stackblitz.io
像这样的用例的迁移路径是什么?
这个确实很棘手。就我个人而言,我认为有两个史诗需要依赖这样的东西将是一种反模式,特别是因为它们都是同步的。我认为这不仅仅是因为它是人为的,否则我认为你不会面临这个问题。
如果 Epic B 真的应该等到 Epic A 准备好才开始,那么父级 (initializeStuffEpic) 应该确保这个序列被强制执行,或者 Epic B 可以监听一些信号来知道 A 准备好了,因为 Epics 是“不应该”泄漏的他们的实现细节是这样的。或者,这可能表明逻辑不应该是两个单独的史诗,而应该是一个,使用函数组合来保持组织有序。
Epics 通常将动作作为它们的信号来响应,尽管第二个参数 ,state$
也是一个 Observable 并且也可以订阅。如果您真的更喜欢以这种方式做事,我认为这可能是最简单的方法:
https://stackblitz.com/edit/redux-observable-playground-g1nuis?file=initialize.js
export const initBEpic = (action$, state$) =>
action$.pipe(
ofType("INITIALIZE_B"),
mergeMap(({ payload }) => {
return state$.pipe(
filter(state => state.initialized.A), // Wait until it is indeed true
take(1), // Very important!
map(() => ({
type: "IS_B_READY",
payload: true
}))
);
})
);
与大多数事情一样,有一些警告。如果 A 从未准备好怎么办?
——
在 redux-observable v1.0 中对操作的调度方式所做的更改旨在使某些事情更直观,同时阻止其他一些不良模式。在那个决定期间没有考虑这个特定的模式,所以我不完全确定我是否会改变行为以使您的用例更容易。虽然不幸的是,看起来很明显的东西不起作用,但它可能是一个可以接受的权衡,因为这是我第一次看到这种情况。
将 Epics 几乎视为独立的进程是有帮助的(尽管它们不是。)如果没有实际信号(操作或 state$ 更新),隐式假设共享状态的时间是不安全的。
我们总是有机会为 v2 更改它,但是有人需要针对特定更改提出建议或 PR,并且调度的工作方式——QueueScheduler 的内部实例——有点复杂。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句