[英]RxJS: Modify Observable array before subscribing
I'm fetching data ( students
via getStudents()
) from an API which returns an Observable.我正在从返回 Observable 的 API 中获取数据( students
通过getStudents()
)。 Within this result I need to get data from two different tables and combine the result.在这个结果中,我需要从两个不同的表中获取数据并组合结果。
Here are my simplified interfaces:这是我的简化界面:
export interface student Student {
id: string
name: string,
school_id: string,
classroom_id: string
}
export interface school School {
id: string,
name: string
}
export interface classroom Classroom {
id: string,
name: string
}
I now need to fetch all students
and add the respective school
and classroom
for each student
via the foreign keys school_id
and classroom_id
.我现在需要获取所有students
,并通过外键school_id
和classroom_id
ID 为每个student
添加各自的school
和classroom
。
My current approach is something like the following.我目前的方法如下所示。 I know it's unfinished but I can't manage to find the right operator and how to properly use it.我知道它尚未完成,但我无法找到合适的操作员以及如何正确使用它。
this.getStudents().pipe(
switchMap(students => {
student.map(student => forkJoin([
this.getSchool(student.school_id),
this.getClassroom(student.classroom_id)
]))
})
)
All of the methods ( getStudents()
, getSchool()
, getClassroom()
) return Observables.所有方法( getStudents()
、 getSchool()
、 getClassroom()
)都返回 Observables。 My goal is to get an array of students
with the respective school
and classroom
data after subscription.我的目标是在订阅后让一系列students
拥有各自的school
和classroom
数据。
I know how to get it done if I need to fetch a single student (eg with getStudent()
) and then use combineLatest
to combine multiple streams.如果我需要获取单个学生(例如使用getStudent()
)然后使用combineLatest
组合多个流,我知道如何完成它。 But when fetching multiple students
it's different.但是当获取多个students
时,情况就不同了。
Thank you in advance!先感谢您!
You need to forkJoin
the observable array that you get from student.map()
and use map
to project the result into the required object.您需要forkJoin
从student.map()
获得的可观察数组,并使用map
将结果投影到所需的 object 中。
const result$ = getStudents().pipe(
switchMap((students: Student[]) =>
forkJoin(students.map(student =>
forkJoin([
getSchool(student.school_id),
getClassroom(student.classroom_id)
]).pipe(map(([school, classroom]) => ({
student,
school,
classroom
}))
)
))
));
What you can do is to covert the original array result to a stream emitting each student and the construct each record one by one.您可以做的是将原始数组结果转换为 stream 发射每个学生并一一构造每个记录。 Once the object is built, you can return it back to a single array result using toArray() .构建 object 后,您可以使用toArray()将其返回到单个数组结果。 I find doing things this way (flattening a stream that emits arrays to a stream that emits individual elements) easier to manage due to the reduced nesting.我发现以这种方式做事(将发出 arrays 的 stream 展平到发出单个元素的 stream 中)由于减少了嵌套而更易于管理。
this.getStudents().pipe(
switchMap(students => students), // emit each element individually
concatMap(student => // construct the student object.
forkJoin({
classRoom: this.getClassroom(student.classroom_id),
school: this.getSchool(student.school_id),
student: of(student)
})
),
toArray() // when all results are built, emit one array result.
);
This technique works best if getStudents() returns a single emission and then completes.如果getStudents()返回单个发射然后完成,则此技术效果最佳。 If the observable stays open, then toArray() will not emit as it only executes when the source observable completes.如果 observable 保持打开状态,则toArray()将不会发出,因为它仅在源 observable 完成时执行。
If it does stay open, but you only want the first array emission then adding take(1) or first() at the start of the pipe will do work.如果它确实保持打开状态,但您只想要第一个阵列发射,那么在 pipe 的开头添加take(1)或first()就可以了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.