Reputation: 4277
In my Angular App i'm making the call to two APIs, one returns generic data about X items and another API returns it's images.
I would do something like run the two calls simultaneously, show the generic data as that API is the one which response should be faster and then i would change the objects i get from the info api with the images get from the other API.
For now my code is a forkJoin of two APIs but at that point i will show the items only when both APIs are completed.
Here is my code:
ngOnInit(): void {
forkJoin([this.negoziService.negozi(), this.negoziService.images()]).subscribe(data => {
this.arrNegozi = data[0];
data[1].map((i) => {
const image = this.arrNegozi.find((d) => d.id === i.id);
image !== undefined
? image.logo = 'data:image/jpg;base64,' + i.img
: image.logo = null;
});
}, error => {
this.errore = error;
})
}
EDIT:
i've just changed my code to combineLatest
as suggested in comments but the code still behave the same way.
combineLatest([this.negoziService.negozi(), this.negoziService.images()]).subscribe(([nagozi, images]) => {
this.arrNegozi = nagozi;
images.map((img) => {
const negozio = this.arrNegozi.find((d) => d.id === img.id);
negozio !== undefined ? negozio.logo = 'data:image/jpg;base64,' + img.img : negozio.logo = 'assets/images/no_image.svg';
})
},
error => {
this.errore = error;
}
)
The usage is to show a skeleton while the images are loading but as soon as it's possible show the text data got from the first API.
Upvotes: 1
Views: 108
Reputation: 438
I think you you can make the independent requests, and take control about responses and how to merge them. In this way you take control over arrNegozi and show them, at the same time take control over arrImages, and show skeleton until arrNegozi are loaded. First try to manage both info as attributes,
arrNegozi: any[]; // I dont know type of your attribute
arrImages: any[] = [];
in ngOnInit You make separates request and manage when merge negozi with images
this.negoziService.negozi().subscribe((negozi) => {
this.arrNegozi = negozi;
// if the request for images response first, and arrImages are already loaded and has data, then merge negozi with images
if(this.arrImages.length > 0){
this.mergeNegoziWithImages();
}
},
error => {
this.errore = error;
}
)
this.negoziService.images().subscribe((images) => {
// save data on your attribute
this.arrImages = images;
// If the request for negozi response first and arrNegozi are already loaded and has data, then merge negozi with images
//
if(this.arrNegozi.length > 0){
this.mergeNegoziWithImages();
}
},
error => {
this.errore = error;
}
)
Implement method to merge your arrNegozi and your arrImages when get available.
mergeNegoziWithImages(){
// I wrote this guessing about your algorithm, feel free to make your own implementation of the union
this.arrImages.foreach((i)=> {
const image = this.arrNegozi.find((d) => d.id === i.id);
image !== undefined
? image.logo = 'data:image/jpg;base64,' + i.img
: image.logo = null;
})
// Maybe you have to slice arrNegozi to change reference in memory to that array and generate ngOnChanges to be execute.
this.arrNegozi = this.arrNegozi.slice();
}
Upvotes: 1