I have a question regarding this code.
let results = [1, 2 ,3 4]
randomArray.forEach( async (e, i) => {
externalApi(e).subscribe(async ({data}) => {
results.push(data);
console.log("result", e);
}, (error) => {
console.log(error)
});
});
As you can see I am iterating over an array to get multiple results from an api and store them in results
, in theory it works but because the call to the api is a promise, the results.push(data)
, is not going to be executed immediately, so I would expect 2 things.
- That results had no values at the end of the iteration
- After some time results will store the values obtained from the api
This in theory happens but I get these results:
// console results
$"result, 1"
$"result, 2"
$"result, 2"
$"result, 1"
$"result, 3"
$"result, 4"
This leaves me confused because, although asyncrona
the job is running correctly, it seems that the iteration is sending multiple requests for each iteration or is what I understand.
That is, I would expect results after a while, but not multiple results from what I think is just one iteration.
In conclusion I would like to know:
- Why is this happening, is there something I'm not understanding here about functions
async
? - What is the correct way to implement the promise response inside an iterator?
At first that also confused me, since I didn't understand what the
Observables
in Angular were , but then when I understood them, I realized that they were very, very useful.It turns out and happens that a
Observable
is a class that allows you to create custom events, events that can come from other events and that are linked to other functions (until we unsubscribe from them).For example we can use:
To create custom events that come from other factory.
Or events created by us:
This code is not mine, it was taken from:
Ionic Realtime Chat with Socket.io
It turns out and happens, that like every event, when one of these is triggered, what is linked to the event is automatically executed and for each time it is executed a value is returned that may or may not be different:
When we subscribe to changes:
Observable.next
We're telling it to call the event body with the last value it returned each time it runsObservable.next
.But what happens, that apparently with each iteration you are subscribing to a new
Observable
:And although one observable should not affect the other, it may be that this observable is being executed when it is created, for this reason in each iteration the results are so different, because your observables are also affecting your variable
results
.By making no longer
1
if no6
or7
observables are subscribed to the same event (or at least the same event body), the event which changes the data of your variableresults
.Conclusion:
It is not the
promises
and theasync
, this result is the fault of theobservables
and thesubscribe
.Which is natural, since normally we do not subscribe several times to the same event... the ideal would be to subscribe only once since it would already be linked to our observable until we decide to cancel it:
As @Riven already answered, these are observables and not promises.
If you want to iterate over the service responses synchronously, you can do the following:
Angular 's
HttpClient
and all observables include a method that allows them to be converted to promises . Just be aware that with this you will only get the first response from the observable. If it's an observable that will respond multiple times, I don't recommend doing this.