Angular RxJS 如何等待多个并行HTTP请求全部完成后执行后续逻辑
forkJoin 仅支持接收 Observable 可观察对象作为入参,你当前代码中提前对请求调用了subscribe,拿到的是Subscription订阅实例,自然无法被forkJoin识别处理。
改造方案
步骤1:改写fillTable、fillTable2方法,返回Observable对象
将原来写在subscribe回调里的响应处理逻辑移到pipe(tap())中,方法直接返回未订阅的请求Observable:
import { tap, Observable, Subscription } from 'rxjs'; // 存储总订阅,后续用于销毁 public SUB_total?: Subscription; public fillTable(): Observable<any> { const searchOBJ = { CreateDateFrom: this.currentDate, CreateDateTo: this.currentDate, ActNumber: this.ActNumber ?? '', vinCode: this.vinCode ?? '', GovNumber: this.GovNumber ?? '', IsFromDashboard: true }; const searchOBJ2 = { ActNumber: this.ActNumber ?? '', vinCode: this.vinCode ?? '', GovNumber: this.GovNumber ?? '', }; // 简化判断逻辑,合并重复参数 const finalParams = (this.ActNumber || this.vinCode || this.GovNumber) ? { ...searchOBJ2, PageSize: this.pageSize, PageNumber: this.currentPage } : { ...searchOBJ, PageSize: this.pageSize, PageNumber: this.currentPage }; return this.searchService.getActSearch(finalParams).pipe( tap(res => { this.Act_Data = []; const headerPagin = JSON.parse(res.headers.get('X-Pagination')); this.elementsLength = headerPagin.totalCount; this.currentPage = headerPagin.currentPage; this.pageSize = headerPagin.pageSize; res.body.forEach(param => this.Act_Data.push(param)); this.ActDataSource = new MatTableDataSource<Element>(this.Act_Data); }) ) } public fillTable2(): Observable<any> { const searchOBJ = { DeclarationCreateDateFrom: this.currentDate.substring(0, 10), DeclarationCreateDateTo: this.currentDate, DeclarationNumber: this.ActNumber ?? '', VinCode: this.vinCode ?? '', TransitNumber: this.GovNumber ?? '', IsFromDashboard: true }; const searchOBJ2 = { DeclarationNumber: this.ActNumber ?? '', VinCode: this.vinCode ?? '', TransitNumber: this.GovNumber ?? '', IsFromDashboard: true }; const finalParams = (this.ActNumber || this.vinCode || this.GovNumber) ? { ...searchOBJ2, PageSize: this.pageSizeDecl, PageNumber: this.currentPageDecl } : { ...searchOBJ, PageSize: this.pageSizeDecl, PageNumber: this.currentPageDecl }; return this.declarationsService.getDeclarations(finalParams).pipe( tap(res => { this.Declaration_Data = []; const headerPaginDecl = JSON.parse(res.headers.get('X-Pagination')); this.elementsLengthDecl = headerPaginDecl.totalCount; this.currentPageDecl = headerPaginDecl.currentPage; this.pageSizeDecl = headerPaginDecl.pageSize; res.body.forEach(param => this.Declaration_Data.push(param)); this.DeclarationDataSource = new MatTableDataSource<Element>(this.Declaration_Data); }) ) }
注:代码中用??空值合并运算符简化了原来的三元判断,同时合并了重复的if/else逻辑,减少冗余代码
步骤2:在ngOnInit中用forkJoin组合两个请求,并行发起
两个请求会同时发出互不阻塞,等全部请求完成、且各自的tap逻辑执行完毕后,就会触发forkJoin的subscribe回调,执行你的后续操作:
import { forkJoin } from 'rxjs'; ngOnInit(): void { this.SUB_total = forkJoin([ this.fillTable(), this.fillTable2() ]).subscribe(([actRes, declarationRes]) => { console.log("两个请求全部完成", actRes, declarationRes); // 此处写你要执行的后续逻辑 }) } // 销毁订阅避免内存泄漏 ngOnDestroy(): void { this.SUB_total?.unsubscribe(); }
轻量兼容方案(不改原有代码结构)
如果不想改动原有fill方法的订阅逻辑,可以用标志位的方式实现等待:
public actDone = false; public declDone = false; // 在fillTable的subscribe回调最后添加 this.actDone = true; this.checkAllDone(); // 在fillTable2的subscribe回调最后添加 this.declDone = true; this.checkAllDone(); public checkAllDone(): void { if(this.actDone && this.declDone) { // 两个请求都完成,执行后续逻辑 console.log("全部请求完成"); } }
这种方案改造成本低,但可维护性差,请求数量多的话会非常繁琐,仅适合临时快速适配。
内容的提问来源于stack exchange,提问作者nevaehteekay
相关产品推荐
相关产品推荐

