以可观察的方式转换数据 [英] Transform data in an Observable
问题描述
我正在从Angular服务的Observable中检索项目列表.在每个项目中,我都有一个包含主题列表的数组.对于每个主题,我都需要再次致电以获取其详细信息(例如名称,说明等).
I'm retrieving a list of items from an Observable on my Angular service. Inside every item, I have an array with a list of subjects. For every subject, I need to make another call to get its details (e.g. name, description, etc.).
数据结构:
- post1
- subjects: ['books', 'cars', 'movies']
有了这个列表,我得到了每个主题的 id
,但是我需要返回一个可观察到的信息,其中包含属于该帖子的所有主题(及其详细信息).
With that list, I have the id
from every subject but I need to return an observable containing all subjects belonging to that post (and their details).
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'});
}
}
它返回一个对象流,但是我想返回一个包含所有主题的数组.
It returns a stream of objects but I'd like to return an array with all subjects.
[演示]
[DEMO]
推荐答案
那是因为您混淆了 Observables.map()
和
That is because you confused .map()
of Observables.map()
and the .map()
of Array.prototype.map()
.
这行特殊代码:
mergeMap((subjects: string[]) => subjects.map((id: string) => this.getSubject(id)))
不返回 Subjects
的数组;相反,它返回一个 Observables
数组,因为该函数内的 subject
参数是一个数组,而不是 Observable
.因此,特定的 .map()
将返回 this.getSubject(id)
的retyrn类型的数组,该数组是 Observables
;确切地是您得到的行为.
does not return an array of Subjects
; instead, it returns an array of Observables
because the subject
argument inside the function is an array, not an Observable
. Hence, that particular .map()
will return an array of the retyrn type of this.getSubject(id)
, which is an array of Observables
; exactly the behaviour you are getting.
如果要将所有 Observables
解析为 Subjects
的数组,则必须使用
If you want to have all the Observables
resolved into an array of Subjects
, you will have to use Observable.forkJoin
. .forkJoin()
combines all the observables and fire them in parallel.
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))])),
);
}
现在您可以在组件中使用它了
Now you can use it in your component:
getSubjects(id).subscribe(values=>{
console.log(values)//returns an array of Subjects
})
请注意, Observables.forkJoin
在发射之前必须等待所有可观察对象完成.
Note that Observables.forkJoin
will have to wait for all observables to complete before firing an emission.
这篇关于以可观察的方式转换数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!