繁体   English   中英

RxJS:订阅前修改 Observable 数组

[英]RxJS: Modify Observable array before subscribing

我正在从返回 Observable 的 API 中获取数据( students通过getStudents() )。 在这个结果中,我需要从两个不同的表中获取数据并组合结果。

这是我的简化界面:

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
}

我现在需要获取所有students ,并通过外键school_idclassroom_id ID 为每个student添加各自的schoolclassroom

我目前的方法如下所示。 我知道它尚未完成,但我无法找到合适的操作员以及如何正确使用它。

this.getStudents().pipe(
   switchMap(students => {
      student.map(student => forkJoin([
         this.getSchool(student.school_id),
         this.getClassroom(student.classroom_id)
      ]))
   })
)

所有方法( getStudents()getSchool()getClassroom() )都返回 Observables。 我的目标是在订阅后让一系列students拥有各自的schoolclassroom数据。

如果我需要获取单个学生(例如使用getStudent() )然后使用combineLatest组合多个流,我知道如何完成它。 但是当获取多个students时,情况就不同了。

先感谢您!

您需要forkJoinstudent.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
      }))
    )
  ))
));

您可以做的是将原始数组结果转换为 stream 发射每个学生并一一构造每个记录。 构建 object 后,您可以使用toArray()将其返回到单个数组结果。 我发现以这种方式做事(将发出 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.
);

如果getStudents()返回单个发射然后完成,则此技术效果最佳。 如果 observable 保持打开状态,则toArray()将不会发出,因为它仅在源 observable 完成时执行。

如果它确实保持打开状态,但您只想要第一个阵列发射,那么在 pipe 的开头添加take(1)first()就可以了。

StackBlitz

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM