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

无法通过Resolver将多个API响应传递至组件求助

问题

我尝试从两个不同的API获取响应并合并为单个对象,传递给Resolver后再将数据送至Document组件加载,但无法正确获取响应。需要实现将多个API调用的结果合并为单个对象返回。

原代码

resolve(): Observable<any> {
  return new Observable(observer => {
    let filterValue = JSON.parse(sessionStorage.getItem('stateFilter-local'));
    if (filterValue?.selection?.length > 0) {
      delete filterValue['selection'];
      sessionStorage.removeItem('stateFilter-local');
      sessionStorage.setItem('stateFilter-local', JSON.stringify(filterValue));
    }
    this.service.getCOALatestLogBookID(false).subscribe({
      next: (response) => {
        if (response['value'][0] != undefined) {
          let maxVaule = response['value'][0].id;
          this.service.getCOALatestLogBookID(true).subscribe({
            next: (result) => {
              const spConfigValue: number = 4999; //+environment.documentsGridLimit;                
              let lobvalue = (+maxVaule / spConfigValue);
              if (!Number.isInteger(lobvalue)) {
                lobvalue = Math.floor(lobvalue) + 1;
              }
              let array = [];
              let initailValue = +result['value'][0].id;
              let endValue = initailValue + spConfigValue;
              for (let f = 0; f < lobvalue; f++) {
                let filter = initailValue + ',' + endValue;
                array.push(filter);
                initailValue = endValue + 1;
                endValue = endValue + spConfigValue;
              }
              this.modelList1=[];
              combineLatest(array.map(number => this.service.getCOALogBookGrid(number, spConfigValue.toString()))).subscribe((res: any) => {
                res.map(item => {
                  console.log('forkJoin - ' + this.modelList.length + ' - ' + item?.['value'].length);
                  this.modelList.push(item);
                  let dd = --array.length;
                  if (dd == 0) {
                    const response = {
                      spListMaxId: maxVaule,
                      spListMinId: result['value'][0].id,
                      model: this.modelList1
                    }
                    this.modelList1=[...this.modelList];
                    observer.next(response);
                    observer.complete();
                  }
                });
              });                
            }
          });
        } 
      } 
    });
    
    this.service.getLatestLogBookID(false).subscribe({
      next: (response) => {
        if (response['value'][0] != undefined) {
          let maxVaule = response['value'][0].id;
          this.service.getLatestLogBookID(true).subscribe({
            next: (result) => {
              const spConfigValue: number = 4999; //+environment.documentsGridLimit;                
              let lobvalue = (+maxVaule / spConfigValue);
              if (!Number.isInteger(lobvalue)) {
                lobvalue = Math.floor(lobvalue) + 1;
              }
              let array = [];
              let initailValue = +result['value'][0].id;
              let endValue = initailValue + spConfigValue;
              for (let f = 0; f < lobvalue; f++) {
                let filter = initailValue + ',' + endValue;
                array.push(filter);
                initailValue = endValue + 1;
                endValue = endValue + spConfigValue;
              }
              combineLatest(array.map(number => this.service.getLogBookGrid(number, spConfigValue.toString()))).subscribe((res: any) => {
                res.map(item => {
                  console.log('forkJoin - ' + this.modelList.length + ' - ' + item?.['value'].length);
                  this.modelList1.push(item);
                  let dd = --array.length;
                  if (dd == 0) {
                    const response = {
                      spListMaxId: maxVaule,
                      spListMinId: result['value'][0].id,
                      model: this.modelList1
                    }
                    observer.next(response);
                    observer.complete();
                    console.log(this.modelList1,"array")
                  }
                });
              });
            }
          });
        }          
      } 
    });
  });
} 
问题分析
  • 嵌套订阅形成回调地狱,逻辑混乱,且没有错误处理,单个API失败会导致整个流程挂起
  • 两个并行的API流各自独立调用observer.next()和observer.complete(),Resolver会收到两次结果,无法合并成单个对象
  • 使用共享变量modelList、modelList1,两个流同时修改会导致数据冲突
  • 手动判断数组长度来触发完成,逻辑冗余且容易出错
解决方案

用RxJS操作符重构代码,避免嵌套订阅,同时合并两个流的结果:

import { forkJoin, switchMap, map, catchError, of } from 'rxjs';

resolve(): Observable<any> {
  // 处理sessionStorage逻辑
  let filterValue = JSON.parse(sessionStorage.getItem('stateFilter-local') || '{}');
  if (filterValue?.selection?.length > 0) {
    delete filterValue.selection;
    sessionStorage.setItem('stateFilter-local', JSON.stringify(filterValue));
  }

  // 封装COA相关API请求逻辑
  const fetchCOAData$ = this.service.getCOALatestLogBookID(false).pipe(
    switchMap(coaMaxRes => {
      if (!coaMaxRes?.value?.[0]) return of(null);
      const maxValue = coaMaxRes.value[0].id;
      return this.service.getCOALatestLogBookID(true).pipe(
        switchMap(coaMinRes => {
          if (!coaMinRes?.value?.[0]) return of(null);
          const spConfigValue = 4999;
          const minValue = coaMinRes.value[0].id;
          const lobValue = Math.ceil(Number(maxValue) / spConfigValue);
          
          // 生成批量请求数组
          const requests = [];
          let initialValue = Number(minValue);
          for (let f = 0; f < lobValue; f++) {
            const endValue = initialValue + spConfigValue;
            requests.push(this.service.getCOALogBookGrid(`${initialValue},${endValue}`, spConfigValue.toString()));
            initialValue = endValue + 1;
          }

          // 并行执行所有COA请求,合并结果
          return forkJoin(requests).pipe(
            map(coaModels => ({
              coaSpListMaxId: maxValue,
              coaSpListMinId: minValue,
              coaModel: coaModels.flatMap(item => item.value || [])
            }))
          );
        })
      );
    }),
    catchError(err => {
      console.error('COA数据请求失败:', err);
      return of(null);
    })
  );

  // 封装普通LogBook相关API请求逻辑
  const fetchLogBookData$ = this.service.getLatestLogBookID(false).pipe(
    switchMap(logMaxRes => {
      if (!logMaxRes?.value?.[0]) return of(null);
      const maxValue = logMaxRes.value[0].id;
      return this.service.getLatestLogBookID(true).pipe(
        switchMap(logMinRes => {
          if (!logMinRes?.value?.[0]) return of(null);
          const spConfigValue = 4999;
          const minValue = logMinRes.value[0].id;
          const lobValue = Math.ceil(Number(maxValue) / spConfigValue);
          
          // 生成批量请求数组
          const requests = [];
          let initialValue = Number(minValue);
          for (let f = 0; f < lobValue; f++) {
            const endValue = initialValue + spConfigValue;
            requests.push(this.service.getLogBookGrid(`${initialValue},${endValue}`, spConfigValue.toString()));
            initialValue = endValue + 1;
          }

          // 并行执行所有LogBook请求,合并结果
          return forkJoin(requests).pipe(
            map(logModels => ({
              logSpListMaxId: maxValue,
              logSpListMinId: minValue,
              logModel: logModels.flatMap(item => item.value || [])
            }))
          );
        })
      );
    }),
    catchError(err => {
      console.error('LogBook数据请求失败:', err);
      return of(null);
    })
  );

  // 合并两个流的结果,返回单个对象
  return forkJoin([fetchCOAData$, fetchLogBookData$]).pipe(
    map(([coaData, logData]) => ({
      coaData,
      logData
    })),
    catchError(err => {
      console.error('数据合并失败:', err);
      return of({ coaData: null, logData: null });
    })
  );
}
关键改进点
  • 用switchMap替代嵌套订阅,扁平化异步逻辑,避免回调地狱
  • 用forkJoin并行执行批量API请求,确保所有请求完成后再返回结果
  • 将COA和LogBook的请求逻辑拆分,各自处理后再合并为单个对象返回
  • 移除共享变量,用数据流传递数据,避免数据冲突
  • 添加catchError处理每个环节的错误,防止单个请求失败导致Resolver挂起
  • 对返回的模型数据做平铺处理,方便组件直接使用

内容的提问来源于stack exchange,提问作者Balachandar K

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 19:14:54