如何在 Redux Observable 中发送一个动作,等待 1 秒,然后再发送两个动作?
How can I dispatch one action, wait 1 second, then dispatch two more actions in Redux Observable?
我将如何在单个史诗中执行以下操作
- 调度 pauseGame()
- 等待 1 秒
- 调度 2 个操作
以下调度最后两个动作但不调度 pauseGame()。
const moveEpic: RootEpic = (action$, state$) =>
action$.pipe(
filter(isActionOf(move)),
map(() => pauseGame()),
filter(() => state$.value.ruleRow.lastMoveSuccessful),
delay(1000),
switchMap(() => [
removeBoardObject(
state$.value.ruleRow.totalMoveHistory[state$.value.ruleRow.totalMoveHistory.length - 1]
.dragged,
),
resumeGame(),
]),
);
pauseGame
没有调度的原因是你没有调度它。您正在调用动作创建者,然后立即将您的可观察状态更改为 lastMoveSuccessful
.
相反,您想要的是拆分管道并将它们 merge
合二为一。我知道这很令人困惑,但这就是 Redux-Observable 目前的工作方式。如果您想要一种可以随时发送的不同方式,请查看我的文章:https://dev.to/sawtaytoes/the-best-practice-anti-pattern-jj6
当出现move
类型时,切换到一个新的observable。该 observable 是 2 个新 observable 的合并:一个立即调度 pauseGame
,另一个检查最后一步是否成功,如果成功,等待一秒钟并调度其他 2 个动作。
const moveEpic: RootEpic = (action$, state$) => (
action$.pipe(
filter(isActionOf(move)),
switchMap(() => (
merge(
of(pauseGame()),
of(state$.value.ruleRow.lastMoveSuccessful).pipe(
filter(Boolean),
delay(1000),
concatMap(() => [
removeBoardObject(
state$.value.ruleRow.totalMoveHistory[
state$.value.ruleRow.totalMoveHistory.length - 1
].dragged
),
resumeGame(),
]),
)
)
)),
);
)
附带说明一下,我不知道您为什么要创建自己的 isActionOf
函数,但通常您应该能够将该行更改为 ofType(move)
。
Evert Bouw 利用 startWith
和 endWith
提供了一个更简单的建议。您将失去管道中的顺序排序,但您不必拆分它:
const moveEpic: RootEpic = (action$, state$) => (
action$.pipe(
filter(isActionOf(move)),
switchMap(() => (
of(state$.value.ruleRow.lastMoveSuccessful).pipe(
filter(Boolean),
delay(1000),
map(() => (
removeBoardObject(
state$.value.ruleRow.totalMoveHistory[
state$.value.ruleRow.totalMoveHistory.length - 1
].dragged
)),
startWith(pauseGame()),
endWith(resumeGame()),
)
)
)),
);
)
请记住,如果您需要知道 endWith
中 state$
的值,则需要使用 finalize
。它接受一个函数而不是一个值。
我将如何在单个史诗中执行以下操作
- 调度 pauseGame()
- 等待 1 秒
- 调度 2 个操作
以下调度最后两个动作但不调度 pauseGame()。
const moveEpic: RootEpic = (action$, state$) =>
action$.pipe(
filter(isActionOf(move)),
map(() => pauseGame()),
filter(() => state$.value.ruleRow.lastMoveSuccessful),
delay(1000),
switchMap(() => [
removeBoardObject(
state$.value.ruleRow.totalMoveHistory[state$.value.ruleRow.totalMoveHistory.length - 1]
.dragged,
),
resumeGame(),
]),
);
pauseGame
没有调度的原因是你没有调度它。您正在调用动作创建者,然后立即将您的可观察状态更改为 lastMoveSuccessful
.
相反,您想要的是拆分管道并将它们 merge
合二为一。我知道这很令人困惑,但这就是 Redux-Observable 目前的工作方式。如果您想要一种可以随时发送的不同方式,请查看我的文章:https://dev.to/sawtaytoes/the-best-practice-anti-pattern-jj6
当出现move
类型时,切换到一个新的observable。该 observable 是 2 个新 observable 的合并:一个立即调度 pauseGame
,另一个检查最后一步是否成功,如果成功,等待一秒钟并调度其他 2 个动作。
const moveEpic: RootEpic = (action$, state$) => (
action$.pipe(
filter(isActionOf(move)),
switchMap(() => (
merge(
of(pauseGame()),
of(state$.value.ruleRow.lastMoveSuccessful).pipe(
filter(Boolean),
delay(1000),
concatMap(() => [
removeBoardObject(
state$.value.ruleRow.totalMoveHistory[
state$.value.ruleRow.totalMoveHistory.length - 1
].dragged
),
resumeGame(),
]),
)
)
)),
);
)
附带说明一下,我不知道您为什么要创建自己的 isActionOf
函数,但通常您应该能够将该行更改为 ofType(move)
。
Evert Bouw 利用 startWith
和 endWith
提供了一个更简单的建议。您将失去管道中的顺序排序,但您不必拆分它:
const moveEpic: RootEpic = (action$, state$) => (
action$.pipe(
filter(isActionOf(move)),
switchMap(() => (
of(state$.value.ruleRow.lastMoveSuccessful).pipe(
filter(Boolean),
delay(1000),
map(() => (
removeBoardObject(
state$.value.ruleRow.totalMoveHistory[
state$.value.ruleRow.totalMoveHistory.length - 1
].dragged
)),
startWith(pauseGame()),
endWith(resumeGame()),
)
)
)),
);
)
请记住,如果您需要知道 endWith
中 state$
的值,则需要使用 finalize
。它接受一个函数而不是一个值。