Im refactoring a billing system made with Angular + NodeJs.
I need to make some API calls to my backend, first to get Customers, then Invoices and finally Students. I call the functions in ngOnInit. Then I need to manipulate the Arrays mixing the data.
If I call the functions in order, sometimes the code can't access all the info, for example:
ngOnInit(): void {
this.getCustomers();
this.getInvoices();
this.getStudents();
this.doSomeCalculations();
Sometimes customers[] (defined by this.getCustomers() is still empty when this.doSomeCalculations() starts.
I tried with setTimeout, with no improvement.
Finally what I did to make everything work was calling getInvoices() in the getCustomers() response, and getStudents() in getInvoices() response. So getInvoices() asign the response to invoices[] and then calls the next function, and so on. And doSomeCalculations() only starts when all the data has been asigned to variables.
But this solution is ugly. I know there is a better way of doing this, but I don't know how. Maybe it is related to promises or async-await?
My base code for the API calls is as follows:
getCustomers(){
this._customerService.getCustomers()
.subscribe(
{ next: (res) => {
this.customers = res;
this.getInvoices();
},
error: (err) => {
console.log(<any>err);
}
}
);
}
It is the same for getInvoices and getStudents.
How can I improve my code here?
You could try using async/await + promises.
For each method definition, you could return the data as a promise, then use async/await at the top level. I see you're using observables for the data calls, but you don't have to. Promises may be better here.
Example:
async ngOnInit(): Promise<void> {
try {
await getCustomers();
...
} ...
}
getCustomers(): Promise<Customers[]>{
return new Promise((err, resp) => {
...
resolve(resp)
})
}