我正在从我的 Angular 服务上的 Observable 中检索项目列表。在每个项目中,我都有一个包含主题列表的数组。对于每个主题,我都需要再次调用以获取其详细信息(例如名称、描述等)。
数据结构:
- post1
- subjects: ['books', 'cars', 'movies']
通过该列表,我获得了每个主题的 id
,但我需要返回一个包含属于该帖子的所有主题(及其详细信息)的可观察值。
AppService.ts
getPost(id: string): Observable<Post> {
return Observable.of({id: id, subjects: ['books', 'cars', 'movies']});
}
getSubjects(id: string): Observable<Subject[]> {
return this.getPost(id).pipe(
map((post: Post) => post.subjects),
mergeMap((subjects: string[]) => subjects.map((id: string) => this.getSubject(id))),
switchMap(list => list),
);
}
getSubject(id: string): Observable<Subject> {
switch (id) {
case 'books':
return Observable.of({id: 'books', name: 'Books'});
case 'cars':
return Observable.of({id: 'cars', name: 'Cars'});
case 'movies':
return Observable.of({id: 'movies', name: 'Movies'});
}
}
它返回一个对象流,但我想返回一个包含所有主题的数组。
[ DEMO ]
最佳答案
那是因为你混淆了Observables.map()
的.map()
以及 Array.prototype.map()
的 .map()
.
这行特定的代码:
mergeMap((subjects: string[]) => subjects.map((id: string) => this.getSubject(id)))
不返回Subjects
数组;相反,它返回一个 Observables
数组,因为函数内的 subject
参数是一个数组,而不是 Observable
。因此,特定的 .map()
将返回 this.getSubject(id)
的 retyrn 类型的数组,它是一个 Observables
的数组>;正是您所得到的行为。
如果您希望将所有 Observables
解析为 Subjects
数组,则必须使用 Observable.forkJoin
。 .forkJoin()
组合所有可观察量并并行激发它们。
getSubjects(id: string): Observable<Subject[]> {
return this.getPost(id).pipe(
map((post: Post) => post.subjects),
mergeMap((subjects: string[]) => Observable.forkJoin([...subjects.map((id: string) => this.getSubject(id))])),
);
}
现在您可以在组件中使用它:
getSubjects(id).subscribe(values=>{
console.log(values)//returns an array of Subjects
})
请注意,Observables.forkJoin
在触发发射之前必须等待所有可观察对象完成。
关于javascript - 转换 Observable 中的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48553022/