转换Observable中的数据

时间:2018-01-31 23:17:27

标签: javascript angular typescript rxjs observable

我正从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]

1 个答案:

答案 0 :(得分:1)

这是因为您混淆了Observables.map().map()Array.prototype.map().map()

这段特殊代码:

 mergeMap((subjects: string[]) => subjects.map((id: string) => this.getSubject(id)))

不会返回Subjects的数组;相反,它返回一个Observables数组,因为函数内的subject参数是一个数组,而不是Observable。因此,该特定.map()将返回retyrn类型this.getSubject(id)的数组,该数组是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必须等待所有可观察量完成才能开始发射。