簡體   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