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



我有一个Workspace模型,一个Request模型。。。现在是CatalogItem模型,它需要像这样将两者结合起来:

{
workspace: Workspace
requests: Request[]
}

我在如何使用getCatalog(): Observable<CatalogItem[]>函数创建它方面遇到了一些困难。。。应该为每个Workspace返回一个CatalogItem,并向其添加任何相关联的Request

我意识到我的尝试还有很长的路要走,但我希望这足以帮助理解我的意图:

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

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

以下是如何实现它,只需按照下面的3个步骤操作即可

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

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

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关于在RxJS Observable 中"展平"数组的最佳方法的帖子

toArray收集所有源发射,并在源完成时将其作为阵列发射。

这里有一个例子:

这个想法是将你的请求链接起来,使它们相互依赖,并产生一个类似于你所布局的某种合并对象。

关键(至少从我的经验来看(是管道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;
}

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

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

相关内容

  • 没有找到相关文章

最新更新