繁体   English   中英

如何在一个史诗 [redux-observable] 中发出两个请求?

[英]How to make two requests inside one epic [redux-observable]?

我对 rxjs 和 redux-observable 很陌生。 我正在尝试在一个史诗中发出两个 ajax 请求,如下所示:

 import { mergeMap, filter, map, catchError } from 'rxjs/operators'; import { of } from 'rxjs'; import { ofType } from 'redux-observable'; import { push } from 'connected-react-router'; export const doSomething = (action$: any, state$: any) => action$.pipe( ofType('SOMETHING_HAPPEND'), filter((action: any) => action.payload.status === 'SOME_ACTION'), mergeMap(() => ajax.getJSON('/api/somewhere').pipe( map(() => push('some_route')), catchError((error: ResponseError) => of(statusChangeError(error))) ) ), filter(() => { const { startTime, endTime } = getFormData(state$.value); return startTime && endTime; }), mergeMap(() => ajax({ url: './api/another', method: 'POST', body: getFormData(state$.value), }).pipe( map(() => push('another_route')), catchError((error: ResponseError) => of(statusChangeError(error))) ) ) );

第一个请求必须始终运行。 第二个请求是有条件的,我有filter 我不确定这是否是做这些事情的正确方法。 它似乎正在工作,除了这部分

map(() => push('some_route')),

在第一个mergeMap没有被调用。 第二个mergeMap的相同部分运行良好。

我究竟做错了什么?

/api/somewhere的请求引发错误。 您的catchError导致从mergeMap ped observable 发出statusChangeError(error)的结果。 由于后续的过滤器运算符会忽略发出的值,因此它不关心该值是否为错误。 因此,如果您的过滤器谓词通过,则第二个mergeMap会收到一个事件。

我建议不要像现在这样使用filtermap ,尤其是filter 您的映射函数会忽略发出的值,并且似乎每次都返回undefined 如果要在发出值时触发副作用,请使用tap运算符。

同样,您的过滤器谓词会忽略发出的值,而是检查一些外部状态。 像这样的结构会使你的程序更难推理。 您可以使 observables 越“纯”(例如发出不可变值),您的代码就越可测试且越合理。

我会发布该答案,它可能不是问题的确切答案。 但这是标题中问题的答案,我想分享我的解决方案。 您可以使用fromPromise并使用这样的普通承诺:

export const fetchUserEpic = action$ =>
  action$.pipe(
    ofType(FETCH_USER),
    mergeMap(() =>
      fromPromise(
        fetchUser()
          .then(userResponse => 
              fetchMoreInfo()
              .then(moreInfoResponse => [userResponse, moreInfoResponse]
            ),
        ),
      ).pipe(
        map(([userResponse, moreInfoResponse]) =>
          fetchUserFullfilledAction(userResponse.data, moreInfoResponse.data),
        ),
      ),
    ),
  );

其中fetchUserfetchMoreInfo返回普通承诺(例如来自axios() )。 如果你不关心顺序,你可以使用Promise.all() 您可以使用async await重写 fetch 函数

使用该解决方案,您可以放松对不同错误处理的控制,但如果您不需要该解决方案,则该解决方案可能是最简单和最简单的解决方案。

暂无
暂无

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

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