I am trying to call the "getData" API over and over for each value in the "myArray" variable. Each time it gets new data from the "getData" call, I am trying to push the result to an array so I can manipulate the values in the "destinationArray" section of code. However, since typescript is not async, it gets to the "destinationArray" code before it's finished in the .subscribe / before it's finished iterating.
I've already tried fixing this with await waitUntil(() => done==true, { timeout: 10015 });
but I keep getting randomly appearing messages in the console saying ERROR Error: Uncaught (in promise): Error: Timed out after waiting for 10015 ms
. The naive answer is to just increase the timeout to infinity, but the actual API call itself does not take 10 seconds, it takes about 1 second (if even that long). How can I make it wait until it's finished iterating / subscribing before it moves onto the "destionationArray" section at the bottom, without seeing that timeout error message in the console?
let dataFromAPIcall: any[] = []
let myArray: any[] = ["hello","world"]
for(let i = 0; i< myArray.length; i ) {
this.GetDataSubScription = this.myService.getData(myArray[i]).pipe( takeUntil(this.ngUnsubscribe) ).subscribe(data => {
dataFromAPIcall.push(data)
if(i 1 == myArray.length) {
done = true
}
});
}
await waitUntil(() => done==true, { timeout: 10015 });
let destinationArray: any[] = [];
for(let i = 0; i < dataFromAPIcall.length; i ) {
destinationArray[i] = [dataFromAPIcall[i].something1, dataFromAPIcall[i].something2]
}
CodePudding user response:
You can zip
your api calls and handle all responses in a reactive way, without using imperative state variables:
After all observables emit, emit values as an array
// creating an array of observables. The requests are not fired yet.
const requests = myArray.map(i => this.myService.getData(i));
const destinationArray: any[] = [];
// passing the request array to the zip function.
// this will actual initiate the requests and emit when ALL
// requests are done
zip(...requests).pipe(
tap(responses => {
// maping responses to destinationArray
destinationArray = responses.map(dataFromAPIcall => [dataFromAPIcall.something1, dataFromAPIcall.something2])
}),
tap(_ => {
// continue here
})
).subscribe();