以下代码可以正常运行:
export const myEpic = (action$: any) => action$.pipe(
ofType("TEST"),
mergeMap(() => concat(
// fires an actionCreator and triggers another epic
of(actionOne()),
// fires an actionCreator
of(actionTwo())
))
);
问题是我需要从actionOne
中获得数据,然后才能actionTwo
被解雇,而且似乎没有发生。所以我想使它像一个异步函数:
export const myEpic = (action$: any) => action$.pipe(
ofType("TEST"),
mergeMap(async () => concat(
of(await actionOne()),
of(actionTwo())
))
);
这会引发错误:
Uncaught Error: Actions must be plain objects. Use custom middleware for async actions.
编辑
其他相关代码:
// main component that loads
constructor(props) {
props.dispatch(init());
}
componentDidUpdate(prevProps) {
if (prevProps.actionTwoFlag !== this.props.actionTwoFlag) {
// do stuff with result from actionOne
// error is thrown here because there's no data
}
}
// actions
export const init = () => ({ type: "TEST" });
export const actionOne = () => ({ type: "ACTION_ONE" });
export const actionOneDone = (result) => ({ type: "ACTION_ONE_DONE", payload: result });
export const actionTwo = () => ({ type: "ACTION_TWO", payload: true });
// epics
export const actionOneEpic = (action$: any) => action$.pipe(
ofType("ACTION_ONE"),
mergeMap(() =>
ajax(..).pipe(
mergeMap(result => concat(
of(actionOneDone(result)),
...
))
)
)
);
);
答案 0 :(得分:0)
有多种解决方法。
1-一种方法是仅在actionTwo上使用 defer()运算符。 defer()运算符将执行的操作是在订阅时执行代码,由于它们是串联的,因此对of(actionTwo())的订阅将在of(actionOne())完成之后进行: / p>
export const myEpic = (action$: any) => action$.pipe(
ofType("TEST"),
mergeMap(() => concat(
of(actionOne()),
defer(() => of(actionTwo()))
))
);
2- 另一个选项只是执行 switchMap(),这也将确保在创建可观察的of(actionTwo())时,of(actionOne ())的观察值已经发出并完成。 switchMap()还确保顺序顺序,因此您可以安全地删除concat()运算符:
export const myEpic = (action$: any) => action$.pipe(
ofType("TEST"),
mergeMap(() =>
of(actionOne()).pipe(switchMap(() => of(actionTwo())))
)
);
编辑:
现在,我想我明白了,尽管我对redux可观察的史诗还不太熟悉。我在这里看到了一个解决方案:Composing and sequencing multiple epics in redux-observable 可能会解决您的第二个问题。在此基础上,我将提出两个建议。
第一个提案:
该提议只是构建了一个史诗般的内容,该史诗首先将动作一推入,然后等待动作一完成以将动作二推入。
export const myEpic = (action$: any) => action$.pipe(
ofType('TEST'),
map(() => actionOne()),
mergeMap(() => {
return action$.pipe(
ofType('ACTION_ONE_DONE'),
take(1),
map(() => actionTwo()),
);
})
);
第二个提案:
一史无前例。由于动作一和动作二是相关的(一个彼此依赖),将两者合并为一个史诗可能是有意义的,就像这样:
export const myEpic = (action$: any) => action$.pipe(
ofType('TEST'),
map(() => actionOne()),
mergeMap(() => {
return ajax(..).pipe(
mergeMap((data) => {
return concat(
actionOneDone(action),
of(actionTwo()).mergeMap(() => /* Do action two */ actionTwoDone())
)
}),
)
})
);
希望这会有所帮助!