如何在Angular Resolver中用forkJoin和mergeMap链式调用HTTP请求?
解决RxJS forkJoin后链式调用操作符的错误及实现方案
错误原因
你遇到的mergeMap is not a function错误,是因为RxJS 6及以上版本中,操作符改为了可管道化(pipeable)的形式,不再直接挂载在Observable的原型上,不能像旧版本那样直接链式调用.mergeMap()。
正确实现方式
基础修正(仅返回后续请求结果)
通过pipe()包裹操作符即可修正错误,代码如下:
import { forkJoin } from 'rxjs'; import { mergeMap } from 'rxjs/operators'; resolve(): Observable<any> { return forkJoin([ this.dataService.getUser(), this.dataService.getSummary() ]).pipe( // 解构forkJoin返回的数组,方便参数使用 mergeMap(([user, summary]) => { return this.dataService.listDetails(summary); }) ); }
保留所有初始化数据(Resolver常用场景)
如果Resolver需要把并行请求的user、summary和后续请求的details一并返回给组件,可以在mergeMap内部通过map合并所有数据:
import { forkJoin } from 'rxjs'; import { mergeMap, map } from 'rxjs/operators'; // 建议定义类型提升代码可读性 interface ResolveData { user: User; // 替换为你的User类型 summary: Summary; // 替换为你的Summary类型 details: Detail[]; // 替换为你的Detail类型 } resolve(): Observable<ResolveData> { return forkJoin([ this.dataService.getUser(), this.dataService.getSummary() ]).pipe( mergeMap(([user, summary]) => { return this.dataService.listDetails(summary).pipe( // 合并所有初始化数据 map(details => ({ user, summary, details })) ); }) ); }
多后续请求的扩展场景
如果还有更多依赖后续请求的操作,可以继续链式使用mergeMap:
resolve(): Observable<ResolveData> { return forkJoin([ this.dataService.getUser(), this.dataService.getSummary() ]).pipe( mergeMap(([user, summary]) => this.dataService.listDetails(summary).pipe(map(details => ({ user, summary, details })))), mergeMap(({ user, summary, details }) => this.dataService.getExtraInfo(details[0].id).pipe(map(extraInfo => ({ user, summary, details, extraInfo })))) ); }
若后续多个请求可并行执行,也可在mergeMap内部再次使用forkJoin:
resolve(): Observable<ResolveData> { return forkJoin([ this.dataService.getUser(), this.dataService.getSummary() ]).pipe( mergeMap(([user, summary]) => { return forkJoin([ this.dataService.listDetails(summary), this.dataService.getRelatedData(summary.id) ]).pipe( map(([details, relatedData]) => ({ user, summary, details, relatedData })) ); }) ); }
内容的提问来源于stack exchange,提问作者ts1993
相关产品推荐
相关产品推荐

