You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 07:36:03