Estoy refactorizando un sistema de facturación hecho con Angular + NodeJs.
Necesito hacer algunas llamadas API a mi backend, primero para obtener Clientes, luego Facturas y finalmente Estudiantes. Llamo a las funciones en ngOnInit. Luego necesito manipular los Arrays mezclando los datos.
Si llamo a las funciones en orden, a veces el código no puede acceder a toda la información, por ejemplo:
ngOnInit(): void { this.getCustomers(); this.getInvoices(); this.getStudents(); this.doSomeCalculations();A veces, clients[] (definido por this.getCustomers() todavía está vacío cuando se inicia this.doSomeCalculations()).
Probé con setTimeout, sin mejoría.
Finalmente, lo que hice para que todo funcionara fue llamar a getInvoices() en la respuesta getCustomers() y getStudents() en la respuesta getInvoices(). Así que getInvoices() asigna la respuesta a facturas[] y luego llama a la siguiente función, y así sucesivamente. Y doSomeCalculations() solo comienza cuando todos los datos se han asignado a las variables.
Pero esta solución es fea. Sé que hay una mejor manera de hacer esto, pero no sé cómo. ¿Quizás esté relacionado con promesas o espera asincrónica?
Mi código base para las llamadas a la API es el siguiente:
getCustomers(){ this._customerService.getCustomers() .subscribe( { next: (res) => { this.customers = res; this.getInvoices(); }, error: (err) => { console.log(<any>err); } } ); }Es lo mismo para getInvoices y getStudents.
¿Cómo puedo mejorar mi código aquí?
Podría intentar usar async/await + promesas.
Para cada definición de método, puede devolver los datos como una promesa y luego usar async/await en el nivel superior. Veo que está usando observables para las llamadas de datos, pero no es necesario. Las promesas pueden ser mejores aquí.
Ejemplo:
async ngOnInit(): Promise<void> { try { await getCustomers(); ... } ...}
getCustomers(): Promise<Customers[]>{ return new Promise((err, resp) => { ... resolve(resp) })}