Ad

How To Combine Two Observables To Create New Observable?

I have two services named 'PatientsService' and 'AppointmentService'. In third service 'AppointedPatientsService', I want to subscribe to AppointmentService to get all booked appointments with patientId and after that I want to repeatedly subscribe to PatientsService.getPatient(patientId) to get Patient's data with patientId. And then, I want to return new array named allAppointedPatients which holds all appointments with patient's data. I tried this...

 getAppointments() {
let allAppointments: Appointment[] = [];
const allAppointedPatients: AppointedPatient[] = [];

return this.appointmentService.fetchAllAppointments().pipe(
  take(1),
  tap(appointments => {
  allAppointments = appointments;

  for (const appointment of allAppointments) {
    this.patientsService.getPatient(appointment.patientId).pipe(
      tap(patient => {
        const newAppointment = new AppointedPatient(patient.firstName,
                                                  patient.lastName,
                                                  patient.address,
                                                  patient.casePaperNumber,

 appointment.appointmentDateTime);
        allAppointedPatients.push(newAppointment);
      })
    ).subscribe();
  }
  return allAppointedPatients;
}),
pipe(tap((data) => {
  return this.allAppointedPatients;
}))
);

}

This is not working and I know there must be better way to handle such scenario. Please help...

Ad

Answer

You are messing up the async code (observables) with sync code by trying to return the allAppointedPatients array synchronously.

Understand first how async code is working in Javascript and also why Observables (streams) are so useful.

Try the code below and make sure you understand. Of course, I was not able to test it so make your own changes if needed.

getAppointments(): Observable<AppointedPatient[]> {
    return this.appointmentService.fetchAllAppointments()
        .pipe(
            switchMap(appointments => {

                const pacientAppointments = [];

                for (const appointment of allAppointments) {

                    // Extract the data aggregation outside or create custom operator
                    const pacientApp$ = this.patientsService.getPatient(appointment.patientId)
                        .pipe(
                            switchMap((pacient) => of(
                                new AppointedPatient(
                                    patient.firstName,
                                    patient.lastName,
                                    patient.address,
                                    patient.casePaperNumber,
                                    appointment.appointmentDateTime
                                )
                            ))
                        )

                    pacientAppoinments.push(pacientApp$);
                }

                return forkJoin(pacientAppointments);
        });
}
Ad
source: stackoverflow.com
Ad