Angular & RxJs Operators : 如何用另一个可观察的请求覆盖对象值(pipe / mergeMap?)

Angular & RxJs Poerators : How to overide object value with another request observable (pipe / mergeMap ?)

我有一个 Api 服务器,我使用以下服务设法从中获取 "Manufacturer" 对象的列表:

export class ManufacturerService {

  private manufacturers: Manufacturer[] = [];
  private manufacturersSubject = new Subject<Manufacturer[]>();
  manufacturersSubject$ = this.manufacturersSubject.asObservable();

  getManufacturersFromRest() {
    this.manufacturers=[];
    this.apiService.getEntriesFromRest('manufacturers').subscribe(
    (data: Manufacturer[]) => { 
            this.manufacturers=data; 
            this.manufacturersSubject.next(this.manufacturers.slice());
        },
    (error) => {...}
    );
  }
}

export class ApiService {

  private baseEndpoint = 'http://fooo/bar/';
  private maxTime = 10000;

  public getEntriesFromRest (option: string): any {
    return this.httpClient.get<any[]>(this.baseEndpoint + option)
        .pipe(
            timeout(this.maxTime),
            catchError(this.handleError),
            map((data) => data['hydra:member'])
        );
  }
}

我的制造商模型如下所示:

export class Manufacturer
 {
  constructor(
    public id: number,
    public companyname: string,
    ...
    public country: Country,
    public stateprov: State,
    public logo: Logo,
  ) {}
}

但是我的 Api 服务器不回答相应字段的国家/州或徽标类型,而是请求获取关联对象的地址,即

/bar/coutries/{id}
/bar/states/{id}
/bar/logos/{id]

我如何使用 RxJs 运算符用其他 http 请求答案覆盖制造商 Observable(国家、州和徽标字段)?类似于:

this.apiService.getEntriesFromRest('manufacturers').pipe(
 mergeMap((manufacturer) => {manufacturer.country = this.countryService.getCountryfromRest(manufacturer.country.split('/').pop());},
 mergeMap((manufacturer) => {manufacturer.state = this.stateService.getSatefromRest(manufacturer.state.split('/').pop());},
 mergeMap((manufacturer) => {manufacturer.logo = this.logoService.getLogofromRest(manufacturer.logo.split('/').pop());},
)
.subscribe(
    (data: Manufacturer[]) => { 
            this.manufacturers=data; 
            this.manufacturersSubject.next(this.manufacturers.slice());
        },

感谢您的帮助,

编辑 1:

  getManufacturersFromRest() {
    this.manufacturers=[];
    this.apiService.getEntriesFromRest('manufacturers').pipe(
        switchMap(
            manufacturer => forkJoin({
                country: this.countrystateService.getCountryObsFromRest(+manufacturer['country'].split('/').pop()),
                state: this.countrystateService.getStateObsFromRest(+manufacturer['state'].split('/').pop()),
                logo: this.logoService.getLogoObsFromRest(+manufacturer['country'].split('/').pop()),
            }).pipe(
                map(results => ({ ...manufacturer as Manufacturer, ...results }))
            )
        )
    ).subscribe(
        (manufacturers: Manufacturer[]) => { 
this.manufacturers=manufacturers;
this.manufacturersSubject.next(this.manufacturers.slice());},
        (error) => {
            this.manufacturerSubject.next(error);
            return throwError(error);
        }
    );
  }

编辑 2:

  getManufacturersFromRest() {
    this.manufacturers=[];
    this.apiService.getEntriesFromRest('manufacturers').subscribe(
        (manufacturers: Manufacturer[]) => { 
            this.manufacturers=manufacturers;
            this.manufacturersSubject.next(this.manufacturers.slice());
        },
        (error) => {
            this.manufacturerSubject.next(error);
            return throwError(error);
        }
    );
  }

一旦你从第一个请求中获得了 Manufacturer 对象,你就可以这样做:

this.apiService.getEntriesFromRest('manufacturers').pipe(
  switchMap(
    m => forkJoin({
      country: this.service.getCountry(m),
      state: this.service.getState(m),
      /* ... */
      logo: this.service.getLogo(m),
    }).pipe(
      map(results => ({ ...m, ...results }))
    )
  )
).subscribe((m) => /* manufacturer with all the needed data */)

forkJoin 可以被赋予一个对象,其键映射到可观察对象。在 return 中,在所有 observable 完成后,您将获得一个具有 相同键 的对象,但不是 observable,键映射到它们的结果值。

如果有帮助的话,这里是解决方案

getManufacturersFromRest() {
    this.apiService.getEntriesFromRest('manufacturers').pipe(
            mergeMap( (manufacts: any[]) => forkJoin(
                manufacts.map((manufact: any) => forkJoin({
                        country: this.countrystateService.getCountryObsFromRest(manufact['country']),
                        stateprov: this.countrystateService.getStateObsFromRest(manufact['stateprov']),
                        logo: this.logoService.getLogoObsFromRest(manufact['logo']),
                    }).pipe(
                        map(results => ({ ...manufact, ...results}))
                    )
                )
            )
        )
    ).subscribe(
        (manufacturers: Manufacturer []) => {
            this.manufacturers=manufacturers;
            this.manufacturersSubject.next(this.manufacturers.slice());
        },
        (error) => {
            this.manufacturersSubject.next(error);
            return throwError(error);
        },
        () => {console.log('Complete');}
    );
}