0
votes

I am trying to make nested calls using rxjs with nested forkjoins. However, I am facing an issue where the outer forkJoin stops returning a result when the inner observable has a flatMap inside it.

Here's the code to illustrate.

  // Only returns a value when the flatMap statements are removed from the inner observables it is waiting for
  searchAdmin(searchKey: string): Observable<[StudentAccountSearchResult[], InstructorAccountSearchResult[]]> {
    return forkJoin(
      this.getStudentAccountSearchResults(searchKey),
      this.getInstructorAccountSearchResults(searchKey)
    );
  }

  private getStudentAccountSearchResults(searchKey: string): Observable<StudentAccountSearchResult[]> {
    return this.getStudents(searchKey).pipe(
      map((students: Students) => students.students),
      // Outer forkjoin in searchAdmin returns when I remove the line below
      flatMap((studentsArray: Student[]) => forkJoin(studentsArray.map(student => this.createStudentAccountSearchResult(student)))),
    );
  }

  private getInstructorAccountSearchResults(searchKey: string): Observable<InstructorAccountSearchResult[]> {
    return this.getInstructors(searchKey).pipe(
      map((instructors: Instructors) => instructors.instructors),
      // Outer forkjoin in searchAdmin returns when I remove the line below
      flatMap((instructorsArray: Instructor[]) => forkJoin(instructorsArray.map(instructor => this.createInstructorAccountSearchResult(instructor))))
    )
  }

Both getStudentAccountSearchResults and getInstructorAccountSearchResults return the proper value when I subscribe to them directly, so there's no error while mapping the observables. Does anyone know why the flatMap in innerObservables causes the outer forkJoin to stop returning any results? Thanks!

I'm on rxjs 6.4

2
forkJoin() will emit only when all its inner observables emit at least once and complete so that's probably the problem with one of your observables.martin
@martin, thanks, yea this turned out to be the case. If an empty array is passed to the flatmap function, it fails to returnJoshua W

2 Answers

0
votes

I'd say the inner forkJoins might be unnecessary since there already is a outer forkJoin. At the moment the resulting code might look something like forkJoin(forkJoin(...), forkJoin(...)). Instead we could pipe all the observables directly to the outer forkJoin. Try the following

private getStudentAccountSearchResults(searchKey: string): Observable<StudentAccountSearchResult[]> {
  return this.getStudents(searchKey).pipe(
    map((students: Students) => students.students.map(student => this.createStudentAccountSearchResult(student))),
  );
}

private getInstructorAccountSearchResults(searchKey: string): Observable<InstructorAccountSearchResult[]> {
  return this.getInstructors(searchKey).pipe(
    map((instructors: Instructors) => instructors.instructors.map(instructor => this.createInstructorAccountSearchResult(instructor))),
  )
}
0
votes

The answer is as @martin posted in a comment for the original post.

I fixed it by checking if the array was empty before doing the flatmap

 private getInstructorAccountSearchResults(searchKey: string): Observable<InstructorAccountSearchResult[]> {
    return this.getInstructors(searchKey).pipe(
      map((instructors: Instructors) => instructors.instructors),
      // Outer forkjoin in searchAdmin returns when I remove the line below
      flatMap((instructorsArray: Instructor[]) => instructorsArray.length > 0 
        ? forkJoin(instructorsArray.map(instructor => this.createInstructorAccountSearchResult(instructor)))
        : of([]))
    )
  }