Angular & Rx Js Poerators: Как переопределить значение объекта с помощью другого наблюдаемого запроса (pipe / mergeMap?) - PullRequest
1 голос
/ 04 мая 2020

У меня есть сервер Api, с которого мне удается получить список объектов «Производитель», используя следующие сервисы:

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 не отвечает для страны / штата или типа Lo go для соответствующих полей, но адрес для запроса запрашивает связанные объекты, т.е.

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

Как я могу использовать Rx Js операторов для переопределения производителей Наблюдаемые (страна, штаты и поля lo go) с другими ответами на HTTP-запросы? Что-то вроде:

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);
        }
    );
  }

Ответы [ 2 ]

0 голосов
/ 07 мая 2020

Вот решение, если оно может помочь

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');}
    );
}
0 голосов
/ 04 мая 2020

Получив объект 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 можно присвоить объекту, ключи которого отображаются на наблюдаемые. В свою очередь, после того, как все наблюдаемые будут завершены, вы получите объект с такими же ключами , но вместо наблюдаемых ключи сопоставляются с их результирующими значениями.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...