我有一个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.
首先使用mergeAll
将Obsevable<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 {} }