0

I'm new in rxjs and after readed tons of articles I feel a bit confused. I have a lot of nested http requests,that fetch data from the API. First request gets the list of my devices, every device contains a list of sensors, every sensor contains a list of temperatures. The first API request returns the devices list with sensors array filled, but the temperatures array are empty. At this point I must do one http request for each sensors to fetch temperatures data.

I tried to use switchmap combined with forkJoin, but in the observable subscription I obtain only the arrays of temperatures. How can I fill temperatures arrays of each sensor?

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

I need all the data returned by the API, not only the last one.

-- UPDATE --

I hope this stackblitz sketch can help you.

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

1
  • 1
    It would be great If you can add a stackblitz with dummy data Commented Nov 5, 2019 at 18:29

2 Answers 2

6

It would be a challenge to get the syntax of your example exactly correct without a stackblitz, so I'm posting one of mine that I know works and hopefully you can extrapolate from there:

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

I broke it into two pieces:

The products$ stream gets all of the products. It looks like you are doing something similar to get all of the devices.

I then get use the products$ stream and get all of the suppliers for that product, defined as allProductsAndSuppliers$.

In the second stream, I first use switchMap to execute another http request for each product.

I then use forkJoin to re-emit the set of products as an array.

Inside the first forkJoin, I use the products array map operator to "loop" through each product. For each product, I use another forkJoin to find all of the suppliers and emit them as an array.

Inside the second forkJoin, I get each supplier as defined in the product's supplierIds property.

I pipe the result through a map operator that builds a Product containing a copy of the product and its list of suppliers.

For reference, my Product interface looks like this:

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

I use the set of supplierIds retrieved with the product to populate the array of suppliers.

Does this look applicable to your scenario?

Sign up to request clarification or add additional context in comments.

Comments

0

I think that what you are trying to do is :

service.getA().pipe(
   switchMap(resultA => forkJoin(of(resultA), service.getB(resultA ))),
   tap(([resultA, resultB]) => console.log({resultA,resultB}))
)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.