RxJs如何动态将存在依赖的同步调用加入forkJoin避免嵌套
解决方案
核心通过Array.reduce动态拼接mergeMap操作符实现需求,完整实现代码如下:
public keys = ['stateId', 'countyId']; populateAll() { let isLoading = true; // 初始流作为触发入口,第一次调用参数为null of(null).pipe( // 扩展运算符传入动态生成的mergeMap操作符数组 ...this.keys.reduce((operators, currentKey, index) => { const currentMergeMap = mergeMap((prevResponse) => { const route = this.baseRoute + currentKey; // 第一步请求参数为null,后续参数由上一步响应处理生成 const params = index === 0 ? null : this.getParamsFromResponse(prevResponse); return this.apiCall(route, params); }); return [...operators, currentMergeMap]; }, []) ) .subscribe({ next: (finalResponse) => { // 所有串行依赖调用全部完成后才会触发此处 isLoading = false; // 此处添加你的后续业务逻辑 }, error: (err) => { isLoading = false; this.errors = err; } }) }
问题A解决说明
- 利用数组reduce方法遍历
keys列表,每遍历一个key就生成对应的mergeMap操作符存入数组,最终通过扩展运算符...把操作符数组传入pipe方法,完全不需要硬编码每个mergeMap,新增调用只需修改keys数组即可。
问题B解决说明
mergeMap的回调函数天然会接收上一步流返回的结果作为入参,我们在每一步的回调里处理参数和路由即可:- 用当前遍历到的key拼接得到对应请求route
- 第一步调用时直接用初始的null作为params,后续调用统一用
getParamsFromResponse处理上一步的响应得到当前请求的params - 把当前接口调用的observable返回给下一个
mergeMap使用
如果需要拿到所有接口的返回值(类似forkJoin的输出效果),可以调整逻辑在每一步把返回值存入数组统一带出:
// 初始流传递空数组用来存储所有接口响应 of([]).pipe( ...this.keys.reduce((operators, currentKey, index) => { const currentMergeMap = mergeMap((prevResultArr) => { const route = this.baseRoute + currentKey; const params = index === 0 ? null : this.getParamsFromResponse(prevResultArr.at(-1)); return this.apiCall(route, params).pipe( map(currentRes => [...prevResultArr, currentRes]) ); }); return [...operators, currentMergeMap]; }, []) ) .subscribe({ next: (allResponses) => { // allResponses是按调用顺序排列的所有接口返回值数组,和forkJoin输出格式一致 console.log(allResponses); } })
内容的提问来源于stack exchange,提问作者Eternalfalter
相关产品推荐
相关产品推荐

