Reputation: 644
I have an array of items which on each element I want to make an HTTP call, wait for it to finish, then make another call, only one at a time.
I tried:
index(item) {
return this.service.index(item).pipe(
map(response => {
// handle success case
}),
catchError(error => {
// handle error case
})
)
}
async processArray(array) {
const promises = array.map(item => this.index(item));
await Promise.all(promises);
}
proccessArray(array);
Also with NGRX Effects:
@Effect()
effect$ = this.actions$.pipe(
ofType<action>(actionTypes.action),
mergeMapTo(this.store.select(getMyArray)),
flatMap((request: any[]) => {
return zip(...request.map(item => {
return this.service.index(item).pipe(
map(response => {
// handle success case
}),
catchError(error => {
// handle error case
})
)
}))
}),
);
Also tried doing it in for
and forEach
loops but they fire all the requests at once. How could I achieve this?
Upvotes: 8
Views: 5110
Reputation: 15663
If you are using promises and want to wait for each promise to resolve before another call is made then (1) you should not use Promise.all as this will wait til all requests are resolved and (2) you need to use a plain old for-loop which enables you to wait for async operations within the loop.
async processArray(array) {
for(var i = 0; i < array.length; i++){
await yourServiceCall();
}
}
As a sidenote: Since you are using async-await, don't forget to convert your observables to promises.
If you want to move away from promises (and async-await) and rely on pure RxJS instead, have a look at concatMap:
Projects each source value to an Observable which is merged in the output Observable, in a serialized fashion waiting for each one to complete before merging the next.
For example:
import { from } from 'rxjs/observable/from';
ngOnInit() {
from(myArray)
.pipe(concatMap(el => yourServiceCall(el)))
.subscribe(/* your logic */);
}
Upvotes: 6