I have an array of image objects.
console.info('gallery', galleryArray);
The length of this array can be different. I have to make a POST request on every item of this array. The next request must be executed only after previous request has finished.
So I tried to make an array of Observable requests like this:
let requests: Observable<Response>[] = [];
galleryArray.forEach((image) => {
requests.push(this._myService.uploadFilesImages(image));
});
console.info(requests);
My service looks like this:
uploadFilesImages(fileToUpload: any): Observable<any> {
const input = new FormData();
input.append('image', fileToUpload);
return this.uploadHttp.post(`${this.endpoint}`, input)
.map(
(res: Response) => res.json()
);
}
The question is how to perform those requests, so that every api call goes only after previous has finished? Help please. I'm new to Angular.
You are looking for the concatMap
operator:
Example
const apiRoot = 'https://jsonplaceholder.typicode.com/';
const urls = [];
for (let i = 0; i < 500; i++) {
urls.push(apiRoot + 'posts/' + (i + 1));
}
Observable.of(...urls)
.concatMap((url: string) => this.http.get(url))
.subscribe((result) => console.log(result));
The concatMap
operator only emits after the current iterated on observable is complete. You get the results of the individual calls in the the subscribe
block.
In your particular case:
Observable.of(...galleryArray)
.concatMap((image) => this._myService.uploadFilesImages(image))
.subscribe((result) => console.log(result));
You can use async
/ await
for that purpose with the Promise resolve:
let requests: Observable<Response>[] = [];
galleryArray.forEach((image) => {
await new Promise(resolve => {
this._myService.uploadFilesImages(image)
.subscribe(result => {
requests.push(result);
// resolve the promise once we have a result
resolve();
});
});
});
// This will only be called once all the api calls have been made
console.info(requests);
Make sure you put async
behind the method where you are executing this code. Link to my answer for a similar question.