在史诗中,发出一个动作,它在完成时会发出更多动作

Posted

技术标签:

【中文标题】在史诗中,发出一个动作,它在完成时会发出更多动作【英文标题】:Within an epic, emit an action that emits more actions when it completes 【发布时间】:2021-07-05 21:19:23 【问题描述】:

我希望 Action1(如下)的史诗作为可观察的 Action3 发出,然后在完成时发出 Action4 和 Action5。

const action1Epic$ = (action$: Observable<IAction1>, state$: Observable<IState>) => 
    action$.pipe(
        withLatestFromState(state$),
        switchMap(([_action,  stateProp ]) => 
            const somethingUninteresting$ = of(action2(stateProp));
            
            const compoundActions$ = of(action3(stateProp)).pipe(
                mergeMap(act =>
                    merge(...[of(action4(act.stateProp)), of(action5(act.stateProp))])
                )
            );
            return merge(somethingUninteresting$, compoundActions$);
        )
    );

Action3 有一个史诗:

const action3Epic$ = (action$: Observable<IAction3>, state$: Observable<IState>) => 
    console.log("Action 3 is really happening!")
    return action$.pipe(
       withLatestFromState(state$),
       switchMap(([_action,  stateProp ]) => 
          console.log("API call is happening!");
          return api.doSomething().pipe(
             map(statePropFromResponse => action3Success(statePropFromResponse)
          );
       )
    );

结果是我看到“行动 3 真的发生了!”的日志。但绝不会“正在发生 API 调用!”。在调度程序中,我看到 Action1、Action2、Action4 和 Action5 已处理,但从未处理 Action3。

【问题讨论】:

您可以通过在action3Epic$ 中的withLatestFromState 之前添加tap(console.log) 并在withLatestFromState(state$.pipe(tap(console.log))), 中仍然在aciton3Epic$ 中进行进一步调试。 我试过了——withLatestFromState 之前的第一个日志永远不会被打印出来。 有没有办法从 action3Epic$ 修改 action$: 参数?如果是这样,您可以这样做:actions$.pipe(shareReplay(1)) 这样当action3Epic$ 返回的内容被订阅时,您将立即收到一个值。 【参考方案1】:

您需要在合并参数中包含 act 本身。

const compoundActions$ = of(action3(stateProp)).pipe(
  mergeMap(act =>
    merge(...[of(act), of(action4(act.stateProp)), of(action5(act.stateProp))])
  )
);

action1 史诗中的 action3 实例 - mergeMap 回调中的 act - 永远不会作为 Redux 操作发出,因为它不是由史诗中返回的 observable 发出的(特别是 compoundActions$)。

您确实订阅了一个发出该操作的可观察对象(of(action3(stateProp) 位),但您仅使用它来创建其他 2 个操作, 这是compoundActions$ 发出的唯一一个。


附言

不相关但希望有帮助:您可以简化创建可观察对象的方式。

merge(...[of(action4(act.stateProp)), of(action5(act.stateProp))]

可以简化为

from([action4(act.stateProp), action5(act.stateProp)])

就此而言 - 我不确定您是否只是简化 SO 示例的现有代码 - 如果您需要做的只是按顺序发出动作 3、4 和 5,那么您可以这样做:

const compoundActions$ = from([
  action3(stateProp),
  action4(stateProp),
  action5(stateProp),
]);

【讨论】:

以上是关于在史诗中,发出一个动作,它在完成时会发出更多动作的主要内容,如果未能解决你的问题,请参考以下文章

基本的 SwiftUI 选择器在屏幕变化时发出严重警告和奇怪的动作

捕获子组件发出的动作

我的 Vue.js Vuex 商店有 2 个发出 GET 请求的操作。第二个动作需要第一个动作的响应才能起作用。怎么做?

如何在同一个史诗中调度多个动作

UIBarButton 不执行动作

如何让 blktrace 工具显示 D 发出的动作