繁体   English   中英

如何在不使用store.dispatch的情况下链接异步操作并等待结果

[英]How to chain async actions and wait for the result without store.dispatch

我正在尝试编写我的INITIALIZE操作,该操作应以以下方式将一些异步操作链接在一起

  1. 调用初始化动作。
  2. 同时调用两个异步操作。
  3. 等待上述操作完成。
  4. 运行其他一项操作。
  5. 完成初始化。

这是我期望的redux流

INITIALIZATION_STARTED => ASYNC_ACTION_A_STARTEDASYNC_ACTION_B_STARTED => ASYNC_ACTION_A_FINISHEDASYNC_ACTION_B_FINISHED => ASYNC_ACTION_C_STARTED => ASYNC_ACTION_C_FINISHED => INITIALIZATION_FINISHED

我设法在我的史诗中使用store.dispatch来实现该流程,我知道这是反模式,它将在1.0.0版本中删除,所以我想知道如何使用纯史诗来实现

我的工作解决方案

export const initEpic = (action$: ActionsObservable<Action>, store) =>
  action$.filter(actions.initialization.started.match)
    .switchMap(action => (
      Observable.forkJoin(
        waitForActions(action$, actions.asyncA.done, actions.asyncB.done),
        Observable.of(
          store.dispatch(actions.asyncA.started(action.payload)),
          store.dispatch(actions.asyncB.started(action.payload)),
        )
      ).map(() => actions.asyncC.started(action.payload))
    )
  );

const waitForActions = (action$, ...reduxActions) => {
  const actionTypes = reduxActions.map(x => x.type);
  const obs = actionTypes.map(type => action$.ofType(type).take(1));
  return Observable.forkJoin(obs);
}

我也一直试图从这样的评论中使用forkEpic

export const initEpic = (action$: ActionsObservable<Action>, store) =>
  action$.filter(actions.initialization.started.match)).mergeMap(action =>
    forkEpic(loadTagsEpic, store, actions.asyncA.started(action.payload))
      .concat(
        forkEpic(loadBranchesEpic, store, actions.asyncB.started(action.payload))
      )
      .map(() => actions.asyncC.started(action.payload))
  );

但不会调度启动动作ASYNC_ACTION_A_STARTED_ASYNC_ACTION_B_STARTED

听起来merge非常适合此操作。 您将开始侦听asyncA.doneasyncB.done ,然后在等待期间通过发出asyncA.startedasyncB.started启动请求。 这两个流合并为一个,因此它以正确的顺序发生,并且其中任何一个发出的动作都由我们的史诗发出,而无需store.dispatch

const initEpic = action$ =>
  action$.filter(actions.initialization.started.match)
    .switchMap(action => (
      Observable.merge(
        waitForActions(action$, actions.asyncA.done, actions.asyncB.done)
          .map(() => actions.asyncC.started(action.payload)),
        Observable.of(
          actions.asyncA.started(action.payload),
          actions.asyncB.started(action.payload),
        )
      )
    )
  );

这是一个JSBin演示: https ://jsbin.com/yonohop/edit ? js,console

它不执行任何ASYNC_ACTION_C_FINISHEDINITIALIZATION_FINISHED事情,因为该问题中未包含该代码,因此不确定该怎么做。 😁

您可能会注意到,这主要是一个常规的RxJS问题,其中的流项目恰好是动作。 这真的很有帮助,因为当您寻求帮助时,您可以向整个RxJS社区询问是否将问题设计为通用RxJS。


请注意,在开始之前我已经听完了。 这通常是最佳做法,以防在started后同步发出done 如果您不先听,那就会错过的。 由于它是异步的,所以没有关系,但是通常还是最佳做法,并且在进行单元测试时会有所帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM