Вложенные запросы API с rxjs на Angular - PullRequest
0 голосов
/ 05 ноября 2019

Я новичок в rxjs, и после прочтения множества статей я чувствую себя немного сбитым с толку. У меня много вложенных http-запросов, которые извлекают данные из API. Первый запрос получает список моих устройств, каждое устройство содержит список датчиков, каждый датчик содержит список температур. Первый запрос API возвращает список устройств с заполненным массивом датчиков, но массив температур пуст. На данный момент я должен сделать один http-запрос для каждого датчика, чтобы получить данные о температуре.

Я попытался использовать switchmap в сочетании с forkJoin, но в наблюдаемой подписке я получаю только массивы температур. Как я могу заполнить температурные массивы каждого датчика?

APIconnector.GetDevices()
    .pipe(
      tap(devices => {console.log(devices)}),
      switchMap(devices => forkJoin(devices.map(device => device.Sensors))),
      tap(sensors => {console.log(sensors)}),
      switchMap(sensors => forkJoin(sensors.map(sensor => {
        const param = {
          MinutesInterval: 30,
          StartDate: stDate,
          EndDate: new Date(),
          SensorIds: [sensor.Id]
        };  
        return APIconnector.GetIntervalRange(param);
      })))
    ).subscribe(data => {      
      console.log(data);
    })

Мне нужны все данные, возвращаемые API, а не только последние.

- ОБНОВЛЕНИЕ -

Надеюсь, этот набросок стека поможет вам.

https://stackblitz.com/edit/angular-txtemn

Ответы [ 2 ]

1 голос
/ 05 ноября 2019

Было бы непросто получить правильный синтаксис вашего примера без стекаблика, поэтому я выкладываю один из моих, который, как я знаю, работает, и, надеюсь, вы сможете экстраполировать оттуда:

  // All products
  products$ = this.http.get<Product[]>(this.productsUrl)
    .pipe(
      tap(data => console.log('Products', JSON.stringify(data))),
      catchError(this.handleError)
    );

  allProductsAndSuppliers$ = this.products$
    .pipe(
      switchMap(products => forkJoin(
        products.map(product =>
          forkJoin(product.supplierIds.map(supplierId => this.http.get<Supplier>(`${this.suppliersUrl}/${supplierId}`)))
            .pipe(
              map(suppliers => ({
                ...product,
                suppliers: suppliers
              } as Product))
            )
        ))
      )
    );

Я разбил его на две части:

Поток products$ получает все продукты. Похоже, вы делаете что-то похожее, чтобы получить все устройства.

Затем я использую поток products$ и получаю всех поставщиков для этого продукта, определенного как allProductsAndSuppliers$.

Во втором потоке я сначала использую switchMap для выполнения еще одного http-запроса для каждого продукта.

Затем я использую forkJoin для переиздания набора продуктов в виде массива.

Внутри первого forkJoin я использую оператор карты массива products для "обхода" каждого продукта. Для каждого продукта я использую еще один forkJoin, чтобы найти всех поставщиков и выдать их в виде массива.

Внутри второго forkJoin я получаю каждого поставщика, как определено в свойстве productIds продукта.

Я передаю результат через оператор карты, который создает Product, содержащий копию продукта и список его поставщиков.

Для справки, мой интерфейс Product выглядит следующим образом:

export interface Product {
  id: number;
  productName: string;
  productCode?: string;
  description?: string;
  supplierIds?: number[];
  suppliers?: Supplier[];
}

Я использую набор поставщиков, полученных вместе с продуктом, для заполнения массива поставщиков.

Применимо ли это к вашему сценарию?

0 голосов
/ 05 ноября 2019

Я думаю, что вы пытаетесь сделать:

service.getA().pipe(
   switchMap(resultA => forkJoin(of(resultA), service.getB(resultA ))),
   tap(([resultA, resultB]) => console.log({resultA,resultB}))
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...