RxJS Epic仅读取首个Promise问题:如何并行处理两个HTTP请求?
问题分析与解决方案
你的核心问题出在**observableFromHttpPromise函数的参数处理**以及RxJS操作符的使用上,咱们一步步拆解:
为什么只拿到第一个请求的数据?
你定义的observableFromHttpPromise只接受单个Promise作为参数,但调用时却传了两个:
observableFromHttpPromise( deps.getList(store), deps.getTargets(store) // 这个参数被函数完全忽略了! )
函数内部只处理了第一个传入的Promise,第二个请求根本没被执行——这就是为什么交换顺序后只能拿到另一个请求的数据,本质上始终只有第一个参数对应的请求在运行。
另外,你的mergeMap用法也有问题:mergeMap的回调函数只接收一个参数(上游Observable发射的值),你写的mergeMap((listResult, targetResult) => {})是错误的,第二个参数永远是undefined。
正确的实现方式:用forkJoin并行处理请求
要同时发起两个独立的HTTP请求并获取两者的结果,RxJS的forkJoin是最适合的工具——它会等待所有传入的Observable都完成后,把结果按顺序打包成一个数组返回。
修改后的Epic代码如下:
const processorsListEpic = (action$, store, deps) => action$.ofType(Type.LIST_ATTEMPT).pipe( switchMap(() => forkJoin([ // 把每个Promise转换成Observable from(deps.getList(store)), from(deps.getTargets(store)) ]).pipe( // 解构forkJoin返回的结果数组 mergeMap(([listResult, targetResult]) => { console.log('Target:', targetResult.data); console.log('List', listResult.data); // 派发两个独立的成功action(原代码的R.mergeAll会合并两个action对象,这大概率不是你想要的) return of( Actions.ListSuccess(listResult?.data), Actions.TargetsSuccess(targetResult?.data) ); }), catchError(error => of(Actions.ListFailure(error))) ) );
关键细节说明:
forkJoin的作用:并行发起两个请求,等待两者都完成后才继续流的处理,完美匹配你需要同时获取两个请求结果的场景。- 数组解构:
forkJoin返回的是结果数组,用[listResult, targetResult]解构可以直接拿到两个请求的响应数据。 - Action派发修正:原代码的
R.mergeAll会把两个Action对象合并成一个,这不符合Redux的Action派发规范——我们需要用of(action1, action2)返回包含两个Action的Observable,Epic会自动依次派发这两个Action。
可选优化:复用你的observableFromHttpPromise
如果你想保留自己的工具函数,可以修改它支持多个Promise参数:
import { forkJoin, from } from 'rxjs'; export const observableFromHttpPromise = (...promises) => { // 把所有传入的Promise转换成Observable,再用forkJoin合并 return forkJoin(promises.map(promise => from(promise))); };
这样原来的调用方式就可以正常工作了,同时保持代码的复用性。
内容的提问来源于stack exchange,提问作者user10104341
相关产品推荐
相关产品推荐

