如何用RxJS通过forEach模式在单个Action中执行多API请求
问题描述
我是React新手,负责修改一个已实现多API调用的现有应用。项目中使用的模式如下例所示:当触发类型为CaseReducerActions<CaseReducers>的mapperActions.selectPolygon Action时,以下代码会执行,调用fetchPolygon函数从AWS Lambda异步获取数据,返回结果由fetchPolygonCompleted函数处理。
let fetchPolygonStatsEpic = (action$: any, state$: StateObservable<RootState>) => action$.pipe( ofType( mapperActions.selectPolygon.type, mapperActions.alterQueryIndexname.type, ), filter(() => state$.value.mapper.selectedPolygon !== undefined), switchMap(() => concat( of(globalActions.startLoading('polygon')), fetchPolygon(state$.value.mapper).pipe( map(result => mapperActions.fetchPolygonCompleted(result)), catchError(e => of(globalActions.errorOccurred(e.message)))), of(globalActions.stopLoading('polygon')), ) ) )
我需要实现的修改如下:
定义了类型Framework:
export type Framework = { .... }
以及该类型的集合:
export const frameworks: {[framework: string]: Framework} = { liveng0: { ... }, liveng1: { ... }, habmosCairngorms: { ... }, spaceintCairngorms: { ... } }
还有一个根据指定Framework获取数据的API方法:
export let fetchHabitats = (requiredFramework: Framework): Observable<FrameworkHabitats> => { ... }
当触发类型为CaseReducerActions<CaseReducers>的mapperActions.initialise Action时,需要执行一段代码,依次对上述4个Framework类型执行4次异步API调用并处理数据。我通过复制粘贴API调用的简单方式已实现需求,但需要改用遍历模式处理每个Framework,同时保持每个API调用的原子性,且仍能通过单个Action触发所有4次调用。
优化实现方案
可以通过以下方式重构代码,消除重复逻辑同时保留原有的顺序执行、原子性特性:
// 封装复用的请求处理逻辑,避免重复编写pipe/map/catchError const createHabitatFetchStream = (framework: Framework) => { return fetchHabitats(framework).pipe( map(result => mapperActions.fetchHabitatsCompleted(result)), catchError(e => of(globalActions.errorOccurred(e.message))) ); }; let fetchHabitatsEpic = (action$: any, state$: StateObservable<RootState>) => action$.pipe( ofType(mapperActions.initialise.type), switchMap(() => { // 将对象形式的frameworks转为数组,方便遍历生成请求流 const frameworkRequestStreams = Object.values(frameworks).map(createHabitatFetchStream); // 用concat串联加载状态和所有请求流,保持顺序执行 return concat( of(globalActions.startLoading('habitats')), ...frameworkRequestStreams, // 展开所有请求流数组 of(globalActions.stopLoading('habitats')) ); }) );
核心逻辑说明
Object.values(frameworks):把键值对形式的frameworks转换为Framework实例数组,统一遍历处理。- 封装
createHabitatFetchStream:将单个请求的业务逻辑抽离,后续修改请求处理逻辑只需维护这一处代码。 ...frameworkRequestStreams:通过展开运算符将数组中的Observable依次传入concat,确保请求按顺序执行(前一个请求完成后才触发下一个),保留原有的原子性。- 整体流程和原代码一致:触发initialise Action后,先发送加载开始动作,依次执行所有请求,最后发送加载结束动作,错误处理逻辑也完全保留。
内容的提问来源于stack exchange,提问作者Martin Bamford
相关产品推荐
相关产品推荐

