簡體   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