【问题标题】:forkEpic, redux-observable 1.0.0-alpha.2, typescriptforkEpic,redux-observable 1.0.0-alpha.2,打字稿
【发布时间】:2018-05-21 12:36:12
【问题描述】:

我有一部史诗

type GetRailwaysEpic = Epic<GetRailwaysActions, AppState>;

const getRailwaysEpic: GetRailwaysEpic = (action$, state$) =>
  action$.pipe(
    filter(isActionOf(getRailways.request)),
    switchMap(a =>
      getRailways(state$.value.mileages.filters.date)
        .then(getRailways.success)
        .catch(getRailways.failure)
    )
  );

当我在任何地方调用 actions.getRailways.request() 时,它会按预期工作(首先请求操作,然后是成功失败)

我还有一部史诗

const initEpic: Epic<FiltersActions, AppState> = (action$, state$) =>
  action$.pipe(
    filter(isActionOf(init)),
    switchMap(({ payload: { date, depotId, locTypeId, railwayId } }) =>
      of(selectDate(date)).pipe(
        concat(
          forkEpic(getRailwaysEpic, state$, getRailways.request())
        )
      )
    )
  );

我的 ForkEpic 函数:

function forkEpic<T extends Action, S>(
  epicFactory: Epic<T, S>,
  state$: StateObservable<S>,
  ...actions: T[]
) {
  const actions$ = ActionsObservable.of(...actions);
  return epicFactory(actions$, state$, null);
}

我想要什么:'init' 动作 -> 'selectDate' 动作 -> 'getRailways.request' 动作 -> 'getRailways.success' | “getRailways.failure”操作

我所看到的:'init' 操作 -> 'selectDate' 操作 -> 'getRailways.success' | “getRailways.failure”操作

“getRailways.request”操作在某处丢失。 我做错了什么?

附: getRailways - 是一个返回承诺的函数 附言我在这里找到了类似的问题How to chain async actions and wait for the result without store.dispatch 但这不是我真正想要的。

【问题讨论】:

    标签: rxjs redux-observable rxjs6


    【解决方案1】:

    所以问题是 forkEpic 函数在本地调用 getRailwaysEpic 并且因为它正在使用 switchMap 它正在吞噬“请求”操作,从而阻止它到达史诗中间件。

    最好的解决方案是将“选择”动作与“请求”动作流连接起来并将其返回,以便由epicMiddleware正确传播回商店,然后由getRailwaysEpic从动作$流中拦截和处理.

    这是代码沙箱中的工作解决方案: https://codesandbox.io/s/375z2qwv1

    这是负责的代码:

    const requestEpic = action$ =>
      action$.pipe(
        filter(a => a.type === 'request'),
        switchMap(a => from(makeRequest()).pipe(map(success)))
      );
    
    const initEpic = action$ =>
      action$.pipe(
        filter(a => a.type === 'init'),
        concatMap(a => of(select(), request()))
      );
    
    const rootEpic = combineEpics(requestEpic, initEpic);
    const epicMiddleware = createEpicMiddleware(rootEpic);
    
    // 1
    // store.dispatch(init());
    // should be:
    // init -> select -> request -> success
    
    // 2
    // store.dispatch(request());
    // should be:
    // request -> success
    

    【讨论】:

    • 我在这里想要的是独立使用 2 个史诗,我的意思是,有机会调度这两个动作(请求和初始化)。如果我使用 concat,我将得到无限循环。
    • @abdurahmanus 我已经调整了答案以显示实现您正在寻找的正确方法,IMO 不需要原始问题中的 forkEpic 函数,在正确方法的地方添加不必要的抽象让epic的流程回到store,然后通过epicMiddleware发出,初始化另一个epic,监听request action
    • 谢谢,它有效!我只是想找到一种方法来组合几个类似于 redux-thunk 的史诗。也许我需要重新考虑我以前的想法。
    • @abdurahmanus 绝对是你需要的,我也是从 redux-thunk 切换的,所以对我来说最大的不同是认为史诗总是分开的,所以你不会直接从一个史诗引用到另一个史诗,但你返回动作,这个动作将进入另一个史诗并打开它。 PS:请采纳答案
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-11
    • 2019-04-23
    • 1970-01-01
    • 1970-01-01
    • 2018-09-29
    • 2018-10-04
    • 1970-01-01
    相关资源
    最近更新 更多