2
votes

I'm trying to load page data on a top level component in Angular 9 using observables (rxjs 6.5.1). When I subscribe to each of these services individually, I can see the data coming back just fine:

ngOnInit(): void {
  const technicianSubscription = this.techniciansClientService.getByTechnicianId(this.technicianId).subscribe(technician => console.log(technician));
  const technicianReviewsSubscription = this.technicianReviewsClientService.getByTechnicianId(this.technicianId).subscribe(technicianReviews => console.log(technicianReviews));
}

When I try to use forkJoin, the data from the subscribe method is never returned:

ngOnInit(): void {
  this.pageDataSubscription = forkJoin({
    technician: this.techniciansClientService.getByTechnicianId(this.technicianId),
    technicianReviews: this.technicianReviewsClientService.getByTechnicianId(this.technicianId),
  }).subscribe(
    // data is never logged here
    data => console.log(data)
  );
}

I've tried passing forkJoin an array of service calls and I've tried using zip as well, to no avail. What's happening here?

1
weird.. it looks it should work actually - topmoon
Both the call getByTechnicianId are happening correctly? Check network console. - Pankaj Parkar
the behavior you describe can be achieved when one of the stream, or both of them emit events, but do not complete. forkJoin only emits an event whenever all of its sources are complete. could you check that version? - Andrei
@Andrei I think this is what's happening. I tried putting a different service in forkJoin and it was successful. So it appears that the technician service call is not completing. Would you suggest using combineLatest like the answer below for my situation? - EJ Morgan
it depends on the situation you are trying to handle. could you provide an observable that technichian service returns? If it is too complicated I think ..getById(...).pipe(take(1)) taking just 1 event from this observable will handle the issue for you - Andrei

1 Answers

1
votes

I would recommend using combineLatest from rxjs. Its easier to use

import {combineLatest} from `rxjs`;

componentIsActive = true;
ngOnInit(): void {
  combineLatest([
    this.techniciansClientService.getByTechnicianId(this.technicianId),
    this.technicianReviewsClientService.getByTechnicianId(this.technicianId),
  ]).pipe(
    map(([technician, technicianReviews]) => ({technician, technicianReviews})),
    takeWhile(() => this.componentIsActive)
  ).subscribe(data => console.log(data));
}