返回由两个不同的Observable组成的合并对象,这些对象具有RxJS依赖项

时间:2019-03-02 21:17:28

标签: javascript angular typescript rxjs

我将解释在解释问题之前使用的上下文,使用Angular和RxJS设计服务。

此模型有一个对象:

{
  id: string;
  title: string;
  items: number[];
}

我通过GET /element/:id获得了这种类型的每个对象(称为“元素”)

每个元素都有一个items: number[],其中包含一个数字数组,每个数字都有一个URL,因此我为每个数字执行新的GET /element/:id/:itemNumber,并返回项目详细信息。该项目的详细信息模型如下:

{
  idItem: string;
  title: string;
}

因此,在我的服务中,我想为组件提供一个方法,该方法将返回一个Observable,它将获得一个对象数组,其中每个对象都具有带有一个加法属性的元素模型,该模型将包含其详细信息的数组。项目。所以,我将展示我拥有的东西:

服务:

getElement(id: string): any {
  return this.http.get<Element>(this.basePath + `/element/${id}`).pipe(
    map(element => this.getAllItemsDetail(element))
}

getAllItemsDetail(element: Element): any {
  return of(...element.items).pipe(
    map(val => this.getItemDetail(element.id, val)),
    concatAll()
  );
}

我的问题是,在map(element => this.getAllItemsDetail(element))方法中的getElement之后,我不理解如何在RxJS中合并它返回的items数组和在具有元素对象的地图。我需要在该映射后添加“任何内容”以计算Object.Assign以合并两个对象。

编辑

使用@ chiril.sarajiu的答案,他给了我一个线索,利用switchMap我可以映射可观察对象(map用于对象,“对结果对象进行计算”)。因此,我的代码不是我所知道的最漂亮的版本...,我将尝试使用它,但是它可以工作。因此,最终代码如下所示:

getElement(id: string): any {
  return this.http.get<Element>(this.basePath + `/element/${id}`).pipe(
    switchMap(element => this.getAllItemsDetail(element)),
    map(result => { return Object.assign({}, result.element, {itemsDetail: result.items})})
  );
}

getAllItemsDetail(element: Element): any {
  const results$ = [];

  for (let i = 0; i < element.items.length; i++) {
    results$.push(this.getItemDetail(element.id, element.items[i]));
  }

  return zip(...results$).pipe(
    map(items => { return Object.assign({}, { element, items })})
  );
}

请注意,如果result $为空,则有关zip不会发出值的可能性,在这种情况下,您可以将of(未定义)添加到result $数组中,并考虑到项目将为[undefined]

1 个答案:

答案 0 :(得分:1)

要映射另一个可观察对象,您应该使用switchMap函数而不是map 所以

getElement(id: string): any {
  return this.http.get<Element>(this.basePath + `/element/${id}`).pipe(
    switchMap(element => this.getAllItemsDetail(element))
}

更新

考虑此medium article