我有两个包含史诗的鸭子(ui和后端)。我需要在完成后端操作后触发两个动作其中一个操作驻留在后端鸭子中,另一个驻留在ui鸭子中。
我从背景动作开始,事情像预期的那样工作。添加第二个操作会给我带来问题,因为我可以到达操作(控制台日志正确),但不能到达reducer(没有日志)
我要解决的挑战是:
- 在一个史诗中开启两个动作
- 在另一个reducer中调度操作
我的代码看起来像这样:
backendDuck的史诗:
fetchFooEpic : (action$, store) =>
action$.pipe(
operators.filter(action => action.type === types.LOAD),
// start added section for second call
operators.switchMap(action => {
const response = operators.from(fetchSomeUrl(action))
.pipe(
operators.of(uiDuck.actions.fetchUserFulfilled(response.props)),
),
operators.catchError(err => {
console.error('Error happened!', err.message)
return rxjs.of({ type: types.ADD_CATEGORY_ERROR, payload: err })
})
return response
}),
// start added section for second call
// original first call
operators.map(a => ({ type: types.ENDACTION, payload: a.payload })),
operators.catchError(err => {
console.error('Error happened!', err.message)
return rxjs.of({ type: types.ADD_CATEGORY_ERROR, payload: err })
})
)
uiDuck:
export actions={
...
fetchUserFulfilled: (value) => {
console.log('hello from action')
return ({ type: types.FETCHUSERFULFILLED, payload: value })
},
...
}
...
export default function reducer(state = initialState, action) {
switch (action.type) {
case types.FETCHUSERFULFILLED:
console.log('hello from reducer')
return {
...state,
user: action.payload,
}
...
原来我以错误的方式组合了这两个调用。为了能够管道化,管道化的可观察对象需要再次返回一个可观察对象。
当映射到另一个redux-action时,在我看来,它不返回一个可观察对象(?)因此,调用需要发生在同一位置的所有期望的redux-action(例如使用concat)
为了完整起见,我努力在注释
中解释代码的所有部分。
import * as operators from 'rxjs'
fetchFooEpic : (action$, store) =>
action$.pipe(
operators.filter(action => action.type === types.LOAD), // Filter
operators.switchMap(action => // restart inner actions on each call
operators.from(fetchSomeUrl(action)) // creating observable from result
.pipe( // starting new flow on observable (self)
//operators.tap(a => console.log('Now running fetchfooepic 2', a)), // dedicated location for sideeffects
operators.switchMap( // restart inner actions on each call
(response) => operators.concat( // Kicking off several actions sequentially (merge() would do that in parallel)
operators.of(uiDuck.actions.fetchUserFulfilled(response)), // addressing the redux action in other reducer
operators.of(({ // addressing the redux action via the type in this duck (ENDACTION is controlled by epics only, no action exists for it)
type: types.ENDACTION,
payload: response
}})),
)),
operators.catchError(err =>{
console.error('Shit happens!', err.message) // errorhandling
return rxjs.of({ type: types.ADD_CATEGORY_ERROR, payload: err })
})
)
)
),
一般来说,这些函数的文档中有一些(或多或少可以理解的)示例https://rxjs.dev/api/index/function/