Redux Observable错误处理:Zip操作符异常跳转问题求解
解决Redux Observable中Zip合并Observable后的错误处理问题
你的问题核心在于单个Observable的catch把错误转换成了普通的next值,导致zip会把这些错误对象当成正常数据合并,进而进入后续的map回调。要解决这个问题,我们需要调整错误处理的时机,让错误流正确冒泡,而不是提前转换成正常action。
方案1:移除单个Observable的catch,在Zip之后统一处理错误
这种方式下,只要其中一个请求失败,zip会立即终止并抛出错误,我们在zip之后的catch里统一处理错误并派发对应的action,完全不需要手动检查返回值:
import { Observable } from 'rxjs'; import axios from 'axios'; export const myEpic = (action$, store) => action$.ofType("SOME_ACTION") .switchMap(action => { const { siteId } = action; // 移除单个请求的catch,让错误自然冒泡 const siteProgram$ = Observable.fromPromise(axios.get(`/url/${siteId}/programs`)); const programType$ = Observable.fromPromise(axios.get('url2')); return Observable.zip(siteProgram$, programType$) .map(([programsResponse, programTypesResponse]) => { // 能走到这里,说明两个请求都成功了,直接处理数据 return siteProgramsAndProgramTypesToFinalSiteProgramsActionMapper( [programsResponse.data, programTypesResponse.data], siteId ); }) .catch(error => { // 这里捕获任意一个请求的错误,派发通用错误action // 也可以根据error的信息区分是哪个请求出错,派发不同的action return Observable.of({ type: 'GENERAL_ERROR', error }); }); });
方案2:保留错误类型区分,用throw传递错误
如果你需要区分是哪个请求出错(比如PROGRAM_FAILURE和OTHER_FAILURE),可以在单个请求的catch里抛出带标识的错误对象,而不是直接返回正常action。这样zip遇到错误时会终止,上层catch可以根据错误标识派发对应的action:
import { Observable } from 'rxjs'; import axios from 'axios'; export const myEpic = (action$, store) => action$.ofType("SOME_ACTION") .switchMap(action => { const { siteId } = action; const siteProgram$ = Observable.fromPromise(axios.get(`/url/${siteId}/programs`)) .catch(error => { // 抛出带类型的错误对象,而不是返回正常action return Observable.throw({ type: 'PROGRAM_FAILURE', error }); }); const programType$ = Observable.fromPromise(axios.get('url2')) .catch(error => { return Observable.throw({ type: 'OTHER_FAILURE', error }); }); return Observable.zip(siteProgram$, programType$) .map(([programsResponse, programTypesResponse]) => { // 仅当两个请求都成功时才会进入这里 return siteProgramsAndProgramTypesToFinalSiteProgramsActionMapper( [programsResponse.data, programTypesResponse.data], siteId ); }) .catch(error => { // 直接派发之前抛出的带类型的错误action return Observable.of(error); }); });
为什么原来的方式不行?
你之前在每个Observable里用catch把错误转换成了Observable.of({ type: 'PROGRAM_FAILURE', error }),这相当于把错误变成了一个正常的next事件。zip操作符会等待所有Observable发出值,哪怕其中一个发出的是错误对象,它也会把这些对象合并成数组传递给map,所以你才需要手动检查是否有错误。
而调整错误处理时机后,错误会以error事件的形式传递,zip会立即终止流并把错误交给上层的catch处理,这样就跳过了map回调,完全不需要手动检查返回值。
内容的提问来源于stack exchange,提问作者JimmyBoy
相关产品推荐
相关产品推荐

