微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在forkJoin中使用mergeMap来获得可观察的对象

如何解决在forkJoin中使用mergeMap来获得可观察的对象

我有几个异步请求的组合,需要一起完成(使用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())作为参数,在执行获取请求时, second(prop2)一个的简单操作,而第三个( prop3 )也取决于 second 作为获取请求中的参数。我试过使用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 };
                })
            )
          }
      ));
    }

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

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

解决方法

  1. 如果类fullData仅用于保存成员变量,则可以改用接口。

  2. 根据您提到的条件,可以将RxJS switchMap(或mergeMap)运算符与map运算符一起使用,以获取所需的对象。

尝试以下

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,prop1: data.prop1,prop2: data.prop2,prop3: data.prop3
      }))
    )
  )
)

return fullDataObservable;
,

我会通过一次解决一个属性然后将所有内容组合在一起来解决这个问题。

  AProp = this.myFirstSrv.getAProp();
  BProp = this.mySecondSrv.getBProp();
  CProp = this.myThirdSrv.getCProp();
  prop1 = this.CProp.pipe(
    mergeMap(CProp => this.propsSrv.getProp1(CProp))
  )
  prop2 = this.AProp.pipe(
    map(AProp => this.propsSrv.getProp2(AProp))
  )
  prop3 = this.BProp.pipe(
    mergeMap(BProp => this.propsSrv.getProp3(BProp))
  )

  fullData$ = forkJoin({
    AProp: this.AProp,BProp: this.BProp,CProp: this.CProp,prop1: this.prop1,prop2: this.prop2,prop3: this.prop3,})

See link to a stackblitz demo

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。