I am facing an issue with the execution order of recursive RxJS Observables in an Angular application. I have a service, RefreshReportService, which is responsible for refreshing reports. The refreshreport method is designed to refresh a report and its nested reports recursively.
The problem is that the recursive calls seem to be running in parallel instead of waiting for the completion of the previous one. Here is a simplified version of the code:
refreshreport(report_name: string): Observable<any> {
let operations_list: any = [];
let primary_key: string = "";
return new Observable((observer) => {
this.ifreportisfromotherreports(report_name, (nestedreports: any[]) => {
if (nestedreports) {
const recursiveCalls = nestedreports.map((nested_report_name) => {
return this.refreshreport(nested_report_name);
});
from(recursiveCalls).pipe(
concatMap((recursiveCall) => recursiveCall)
).subscribe({
next: (response: any) => { console.log(response); },
error: (err) => { console.log(err); },
complete: () => {
// Continue with the rest of the logic after recursive calls
observer.complete();
}
});
}
const token = localStorage.getItem('auth-token');
const headers = new HttpHeaders({
'Authorization': `token ${token}`
});
const formData = new FormData();
formData.append('report_name', report_name);
this.http.post('http://127.0.0.1:8000/getreportoperationslist', formData, { headers, withCredentials: true }).subscribe({
next: (response: any) => {
operations_list = response.operations_list;
primary_key = response.primary_key;
},
error: (err) => {
console.log(err);
},
complete: () => {
const updateapicalls: Observable<any>[] = [];
operations_list.forEach((operation: any) => {
updateapicalls.push(this.createRequestObservable(operation));
});
from(updateapicalls).pipe(
concatMap((observable) => observable)
).subscribe({
next: (response: any) => { console.log(response); },
error: (err) => { console.log(err); },
complete: () => {
this.DeleteReport(report_name, primary_key);
observer.complete(); // Notify the outer observer that this recursion is complete
}
});
}
});
});
});
}
I want the recursive calls to run sequentially, waiting for the completion of the previous one before moving on to the next. Any insights into how I can achieve this would be greatly appreciated!
This is snap of the networks tab in here, the first one is of the most-outer function, while the second one is of the recursive function (which is correct), but the things screw up from the 3rd one, which of the outer one.. and further calls are all incorrect order of calls
I tried to run the code, but the order is not correct, i expected correct order of calling, first the function calls of the inside one’s and then the outer one’s.
2
Answers
The issue was : not waiting for the updateapicalls[] to get completed ( by applying await ) which made the control to shift back to the parent function, This is the updated code for the same ` async refreshreports(report_name: string): Promise { // Get nested reports (if any) const nestedReports: string[] | undefined = await new Promise((resolve, reject) => { this.ifreportisfromotherreports(report_name, (nestedreports: any[]) => { if (nestedreports) { resolve(nestedreports); } else { resolve(undefined); } }); });
`
Complete will run after each api call in this pattern instead could you try this?
toArray -> ensure
next
orcomplete
will run after all the sequential executions!