将嵌套的HTTP请求合并为单个可观察的

时间:2020-08-19 19:57:13

标签: angular rxjs observable

我有一个工作区模型,一个Request模型...和现在的CatalogItem模型,需要将这两个模型结合起来:

{
  workspace: Workspace
  requests: Request[]
}

我在如何使用getCatalog(): Observable<CatalogItem[]>函数创建此函数时遇到了一些困难...该函数应该为每个CatalogItem和任何关联的{{ 1}}添加到其中。

我意识到自己的尝试还遥遥无期,但我希望它足以帮助理解我的意图:

Workspace

3 个答案:

答案 0 :(得分:1)

看看您的代码,似乎您需要为每个http.get<Request[]>调用workspace

此处是实施方法,只需按照以下3个步骤操作即可。

1。
首先使用mergeAllObsevable<Workspace[]>(由get<Workspace[]>返回)转换为流(以便我们一次可以处理一个workspace)。

2。
接下来使用mergeMap通过调用Observable<Workspace>将每个Observable<CatalogItem>转换为http.get<Request[]>并在使用CtalogItem到达响应后形成一个新的map(利用闭包参考workspace)。

3。
最后使用toArray将流转换回数组。


getCatalog(): Observable<CatalogItem[]> {
  return this.http.get<Workspace[]>(`URL/workspace`).pipe(

   // 1  
    mergeAll(),

   // 2  
    mergeMap(workspace => this.http.get<Request[]>(`URL/${workspace.id}`).pipe(
      map(requests => ({ workspace, requests })))
    ),

   // 3  
    toArray()

  )
}

mergeAll可以将包含数组的Observable展平为流,有关进一步的解释,请参见@Martin's post,以了解在RxJS Observable中“展平”数组的最佳方法。

toArray收集所有源发射,并在源完成时将它们作为数组发射。

答案 1 :(得分:1)

Here's an example:

这个想法是将您的请求链接在一起,使它们彼此依赖,并使结果成为某种合并对象,就像您布置的那样。

关键(至少从我的学习中得知)是管道处的toArray

  getTodos(): Observable<SomeMergedObject[]> {
    return this.http.get<TodoItem[]>('https://jsonplaceholder.typicode.com/todos').pipe(
      mergeMap( resp => resp),
      concatMap( (t: TodoItem) => {
        console.log(t.userId)
        return this.http.get<User>(`https://jsonplaceholder.typicode.com/users/${t.userId}`).pipe(
          map( user => ({ todoItem: t, user } as SomeMergedObject))
        )
      }),
      toArray()
    );
  }

接口

interface TodoItem {
  userId: number;
  id: number;
  title: string;
  completed: boolean;
}

interface User {
  id: number,
  name: string,
  username: string,
  address: object,
  phone: string;
  website: string;
  company: object;
}

interface SomeMergedObject {
  todoItem: TodoItem;
  user: User;
}

答案 2 :(得分:0)

您可以使用内部管道来解决您的问题:

getCatalog(): Observable<CatalogItem[]> {
  return this.http.get<Workspace[]>(`${this.baseUrl}/workspace`).pipe(
    switchMap(workspace => this.http.get<Request[]>(`${this.baseUrl}/${ws.id}/requests`).pipe(
      map(requests => ({workspace, request}))
    )
  );
}

详细信息:

  • 如果在switchMap内打开另一个pipe,则仍具有switchMap的上下文。这意味着您可以使用workspace
  • 如果变量名是您想要作为属性的键(例如const key = 'test'),则可以简写{ key }。这将创建一个对象{ key: 'test }
  • 如果要在地图内返回对象,则可以写({ ... })而不是{ return {} }