【问题标题】:Nested API Requests with rxjs on AngularAngular 上使用 rxjs 的嵌套 API 请求
【发布时间】:2019-11-05 18:27:48
【问题描述】:

我是 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 返回的所有数据,而不仅仅是最后一个。

-- 更新--

我希望这个 stackblitz 草图可以帮助到你。

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

【问题讨论】:

  • 如果您可以添加带有虚拟数据的堆栈闪电战,那就太好了

标签: angular rxjs


【解决方案1】:

如果没有堆栈闪电战,要让您的示例的语法完全正确将是一个挑战,所以我发布了一个我知道有效的示例,希望您可以从那里推断:

  // 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 中,我获取了产品的 supplierIds 属性中定义的每个供应商。

我通过一个地图操作员管道结果,该操作员构建了一个Product,其中包含产品的副本及其供应商列表。

作为参考,我的产品界面如下所示:

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

我使用与产品一起检索到的一组供应商 ID 来填充供应商数组。

这看起来适用于您的场景吗?

【讨论】:

    【解决方案2】:

    我认为你想要做的是:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-11
      • 1970-01-01
      • 1970-01-01
      • 2016-09-14
      • 1970-01-01
      相关资源
      最近更新 更多