javascript - Angular 8 + RxJS 以及合并 flatMap 和 forkJoin 的问题

标签 javascript angular angular8 rxjs6 flatmap

我正在尝试根据前一个请求发出多个 http 请求,并将返回的数据组合到最终结果对象。

我有两个端点:

  1. /properties 它返回给我类似的东西:

    { 
      "data":[ 
        { 
          "id":1,
          "name":"Property 1",
          "units":[ 
            { 
              "id":1,
              "name":"Property 1 - Unit 1",
            },
            { 
              "id":2,
              "name":"Property 1 - Unit 2",
            },
          ],
        },
        { 
          "id":2,
          "name":"Property 2",
          "units":[ 
            { 
              "id":3,
              "name":"Property 2 - Unit 3",
            }
          ]
        }
      ]
    }```
    
  2. /properties/${property.id}/units/${unit.id}/bookings 它返回我一些与先前请求相关的对象,例如:

    {
      "data": {
        "id": 1
      },
      "meta": {
        "count": 5
      }
    }
    

我想要实现的是将这两个响应在单个单元级别上合并为一个。 像这样:

{
  [
    ...

    { 
      "id":2,
      "name":"Property 2",
      "units":[ 
        { 
          "id":3,
          "name":"Property 2 - Unit 3",
          "bookings_meta": {
            "count":5
          }
        }
      ]
    }
  ]
}

我创建了这样的东西,它工作正常:


    list(): Observable<any> {
      return this.http.get('/properties').pipe(
        map((results: any) => results.data),

        flatMap((properties: any[]) => {
          if (properties.length > 0) {
            return forkJoin(properties.map((property: any) => {
              return forkJoin(property.units.map((unit: any) => {
                return this.http.get(`/properties/${property.id}/units/${unit.id}/bookings`).pipe(
                  map(({ meta }) => {
                    unit.bookings_meta = meta
                    return unit;
                  })
                )
              }))
            }))
          }
          return of([]);
        })
      );
    }


    this.list().subscribe(response => {
        console.log(response)
    })

但我认为这不是 100% 正确的解决方案。 我感觉有太多的 forkJoin ,也许它不应该出现在 flatMap 中?

单位之间的预订请求应该是独立的。

有人知道如何改进上面的代码吗?

最佳答案

forkJoin会在所有调用完成后返回数据并返回结果

const combined = Observable.forkJoin(
  this.http.get('https:// ...properties').map((res: Response) => res.json()),
  this.http.get('https:// ..properties/${property.id}/units/${unit.id}/bookings')
      .map((res: Response) => res.json())
)

combined.subscribe(latestValues => {
    console.log( "latestValues" , latestValues );
});

更新:

可以使用 flatMap 运算符将一个 Observable 发出的项转换为另一个 Observable。它创建一个内部 Observable 并将其结果平铺到外部流。

list(): Observable<any> {
    return this.http.get('/properties')
        .flatMap(properties => properties.map(p => p.units.map(unit => 
        {
            this.http.get(`/properties/${property.id}/units/${unit.id}/bookings`)   
        })))
        .subscribe(res => { // some actions });
}

关于javascript - Angular 8 + RxJS 以及合并 flatMap 和 forkJoin 的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59531241/

相关文章:

angular - 如何在不丢失准备好的 css 的情况下在 Ionic 2/3 中编写自定义组件?

angular - 在 Angular Material 8 中将 utc+0 与 MAT_DATE_LOCALE 结合使用

Angular - 找不到名称的管道

angular - array.push() 制作的数组有元素但不能使用 angular

javascript - Backbone.js + Require.js : Collection URL set, 但出现错误 "Uncaught Error: A "url“必须指定属性或函数”

javascript - 使用javascript在html中隐藏多个元素

javascript - RxJS 中的 Promise 'finally' 回调等价物

angular - 表单控件设置值和更新有效性的方法

javascript - 如何使用 javascript/jquery 更改 flexbox 元素的宽度

azure - 将 Angular 2 应用程序部署到 Azure