【问题标题】:Return a merged object composed by two different Observables with dependencies with RxJS返回一个由两个不同的 Observable 组成的合并对象,这些 Observable 依赖于 RxJS
【发布时间】:2023-03-13 01:05:02
【问题描述】:

我将解释我在解释使用 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()
  );
}

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

编辑

@chiril.sarajiu 的回答给了我不止一个线索,switchMap 我可以映射 observable(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 })})
  );
}

请注意,如果 results$ 为空,zip 可能不会发出值,在这种情况下,您可以将 of(undefined) 添加到 results$ 数组中,然后考虑到项目将是 [undefined]

【问题讨论】:

    标签: javascript angular typescript rxjs


    【解决方案1】:

    要映射另一个 observable,您应该使用 switchMap 函数而不是 map 所以

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

    更新

    考虑一下medium article

    【讨论】:

    • 好的,但是有什么区别呢?在 switchMap 之后,如何在管道中使用首先返回的元素(元素)和 getAllItemsDetail 返回的对象?这是我的问题,我需要在该方法中进行合并并返回它,我认为...你明白我的意思吗?
    • 稍后我将提供一个关于 stackblitzz 的示例。
    • 谢谢你!我明白了,别担心,我和你一样使用了 switchMap,并且在 getAll... 方法中我映射了两个对象,而 switchMap 当然两者都有,不要浪费你的时间,因为你帮助了很多,而且我有它;D
    • 很高兴为您提供帮助!希望看到实现,如果它在 github 上的话:D
    • 很好,不过只有一件事,在这里{element: element, items: items} 你可以省略第二项,它可以在没有它们的情况下工作{ element, items }
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-25
    • 2021-09-26
    • 1970-01-01
    • 2016-08-06
    • 2017-11-01
    • 1970-01-01
    • 2018-08-17
    相关资源
    最近更新 更多