首页 > 解决方案 > 在 forkJoin 中使用 mergeMap 来获取依赖于另一个的 observables

问题描述

我有几个需要一起完成的异步请求的组合(使用 forkJoin 完成) - 这样做时,我启动了一个对象:

    export class fullData
    {
        AProp  : any;
        BProp  : any;
        CProp  : any;
    }
    const fullDataObservable : fullData = forkJoin(
    {
        AProp : this.myFirstSrv.getAProp(), 
        BProp : this.mySecondsSrv.getBProp(),
        CProp : this.myThirdSrv.getCProp()
    });
    return fullDataObservable;      

到目前为止,一切都很好。现在 - 我在这个对象中有3 个新属性:

    export class fullData
    {
        AProp  : any;
        BProp  : any;
        CProp  : any;
        prop1 : any;
        prop2 : any;
        prop3 : any;
        
    }

然后第一个prop1)取决于 CProp 值(或 this.myThirdSrv.getCProp())作为参数,在执行 get 请求时,第二个(prop2)一个的简单操作,第三个( prop3 ) 也取决于第二个作为获取请求中的参数。我试过使用mergeMap,但没有用。我究竟做错了什么 ?:

    gatherAllRelevantData() : any
      {
        //this.myService.getProp1() return observable after get request 
        this.myService.getProp1().pipe
        (
          mergeMap((prop1Value : any[]) => 
          {
            //this.myService.getResultAfterSimpleManipulation return object, not observable
            let prop2Values : any[] = this.myService.getResultAfterSimpleManipulation(prop1Value);
            //the this.getProp3Value return observable aftet get request
            return this.getProp3Value(prop2Value).pipe(
              map(prop3Values => 
                {
                  return { prop1 : prop1Value, prop2 : prop2Values, prop3 : prop3Values };
                })
            )
          }
      ));
    }

这一切都应该在一个解析函数中完成,并且应该通过从 this.gatherAllRelevantData 获取数据(没有发生)并且不需要执行 this.gatherAllRelevantData 来启动 fullData 对象:

    resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> 
    {
      const fullDataObservable = forkJoin(
      {
        AProp : this.myFirstSrv.getAProp(), 
        BProp : this.mySecondsSrv.getBProp(),
        CProp : this.myThirdSrv.getCProp(),
        prop1 : this.gatherAllRelevantData().map(item => items.prop1),
        prop1 : this.gatherAllRelevantData().map(item => items.prop1),
        prop1 : this.gatherAllRelevantData().map(item => items.prop1)
    });
    return fullDataObservable; 
  } 

标签: angularrxjsfork-joinmergemap

解决方案


  1. If the class fullData is only used to hold the member variables, you could use an interface instead.

  2. Based on the conditions you've mentioned you could use RxJS switchMap (or mergeMap) operator along with the map operator to get the object of your requirement.

Try the following

export interface fullData {
  AProp: any;
  BProp: any;
  CProp: any;
  prop1: any;
  prop2: any;
  prop3: any;
}

const fullDataObservable: Observable<fullData> = forkJoin({ // <-- it's of type `Observable<fullData>`, not `fullData`
  AProp: this.myFirstSrv.getAProp(), 
  BProp: this.mySecondsSrv.getBProp(),
  CProp: this.myThirdSrv.getCProp()
}).pipe(
  switchMap(data =>
    this.someService.getProp1(data.CProp).pipe( // <-- get `prop1` that depend on `data.CProp`
      map(prop1 => ({
        AProp: data.AProp,
        BProp: data.BProp,
        CProp: data.CProp,
        prop1: prop1,
        prop2: this.simpleManipulate(prop1) // <-- get `prop2` that depend on `prop1`
      }))
    )
  ),
  switchMap(data =>
    this.someService.getProp3(data.prop2).pipe( // <-- get `prop3` that depend on `data.prop2`
      map(prop3 => ({
        AProp: data.AProp,
        BProp: data.BProp,
        CProp: data.CProp,
        prop1: data.prop1,
        prop2: data.prop2,
        prop3: data.prop3
      }))
    )
  )
)

return fullDataObservable;

推荐阅读