Angular RxJS多次调用同一API如何标记返回结果并合并
问题场景
- 业务需要携带不同payload多次调用同一API,当前已实现多请求返回对象数组的合并功能
- 新增需求:按调用顺序给每次请求返回的所有对象追加
api_id标记,第1次调用返回对象的api_id值为"1",第2次为"2",以此类推,用于后续数据过滤
原有实现代码如下:
public GetTriplets(args: {payload: any, limit: number}[]) { const urls = []; args.forEach(arg => urls.push(this.http.post(environment.url+ `/data/docs?limit=${arg.limit}`, arg.payload)) ); return merge(...urls).pipe( reduce((result:[], response:[]) => result.concat(response)), mergeMap( (res: []) => res && res.length > 0 ? of(res) : throwError('There are no docsfor the selected parameters.') ) ); }
实现方案
原有实现直接将所有请求Observable传入merge,会丢失请求和序号的对应关系,无法正确给返回值打标。只需要在构造请求阶段绑定每个请求的序号,在单请求返回时提前给当前响应的所有对象追加标记即可,修改后代码如下:
import { merge, of, throwError } from 'rxjs'; import { reduce, mergeMap, map } from 'rxjs/operators'; public GetTriplets(args: {payload: any, limit: number}[]) { // 遍历参数时携带索引,为每个请求绑定对应序号 const requests = args.map((arg, index) => { const apiId = String(index + 1); return this.http.post<Array<Record<string, any>>>( `${environment.url}/data/docs?limit=${arg.limit}`, arg.payload ).pipe( // 单请求返回时,先给当前响应的所有对象加上对应api_id标记 map(responseList => responseList.map(item => ({...item, api_id: apiId}))) ) }); return merge(...requests).pipe( reduce((result: any[], response: any[]) => result.concat(response)), mergeMap( (res: any[]) => res && res.length > 0 ? of(res) : throwError('There are no docs for the selected parameters.') ) ); }
修改点说明
- 构造请求列表时使用带索引的
map遍历参数,索引从0开始,对应请求序号为索引值加1,转为字符串后作为当前请求所有返回对象的api_id值 - 给每个HTTP请求单独追加
map操作,拿到单次请求的响应数组后,遍历每一项通过对象展开追加api_id属性,不修改原有响应的其他字段 - 修正了原有报错信息里
docsfor的拼写问题,改为docs for - 补充了TS类型标注,避免隐式any类型的问题
内容的提问来源于stack exchange,提问作者breach
相关产品推荐
相关产品推荐

