简体   繁体   English

Angular 8 + RxJS 以及结合 flatMap 和 forkJoin 的问题

[英]Angular 8 + RxJS and problem with combine flatMap and forkJoin

I'm trying to make multiple http requests depends of previous one and combine returned data to final result object.我正在尝试使多个 http 请求依赖于前一个请求并将返回的数据组合到最终结果对象中。

I have two endpoints:我有两个端点:

  1. /properties which returns me something like that: /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 which returns me some object related to previous request for instance: /properties/${property.id}/units/${unit.id}/bookings返回一些与先前请求相关的对象,例如:

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

What I would like to achieve is combine those two responses into one on single unit level.我想要实现的是在单个单元级别将这两个响应合并为一个。 Like this:像这样:

{
  [
    ...

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

I created something like this and it works fine:我创建了这样的东西,它工作正常:


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

But I think it is not in 100% correct solution.但我认为这不是 100% 正确的解决方案。 I'm feeling there are too many forkJoin and maybe it shouldn't be there flatMap ?我觉得forkJoin太多了,也许它不应该存在flatMap

The requests for bookings between units should be independent.单元之间的预订请求应该是独立的。

Some one have an idea how to improve the code above?有人知道如何改进上面的代码吗?

forkJoin will return data when all calls are finished and return result 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 );
});

UPDATE:更新:

It is possible to transform items emitted by an Observable into another Observable by using the flatMap operator.可以使用flatMap运算符将 Observable 发出的项目转换为另一个 Observable。 It creates an inner Observable and flats its result to the outer stream.它创建一个内部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 });
}

Finally I found an answer for the observable hell :)最后,我找到了可观察地狱的答案:)

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

    mergeMap((properties: any[]) => forkJoin(
      properties.map((property: any) => forkJoin(
        property.units.map((unit: any) => this.http.get(`/properties/${property.id}/units/${unit.id}/bookings`).pipe(
          map(({ meta }) => ({ ...unit, meta }))
        ))
      )).pipe(map((units: any[]) => ({ ...property, units }))))
    ))
  );
}

Cheers!干杯!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM