How can I use RxJS to process my multiple api calls in an Angular service?
How can I use RxJS to process my multiple api calls in an Angular service?
Problem: I want to get data from the Star Wars Api(SWAPI). I want to make an initial http call, and then in that same call, get values from 2 additional api calls. Swapi returns a json object, but its values are also urls to other parts of their api.
Currently, this code works, but I'm only able to retrieve the character object, and then the homeworld object.
Here is my code:
question.service.ts
getCharacter() {
const random = Math.floor(Math.random() * 10) + 1;
let characterUrl = `https://swapi.co/api/people/${random}/`;
this.http.get(characterUrl).pipe(
mergeMap((character:any) => {
this.character = character;
//I tried using forkJoin(this.http.get(character.species), this.http.get(character.homeworld)), but it wasn't working.
//In total, I want to get the original character object, and also the species/homeworld values.
return this.http.get(character.homeworld);
})
//logs out the homeworld value, but I'd also like the species value.
).subscribe(v => console.log(v))
}
This is the code I'm trying to refactor from:
question.component.ts
this.questionService.getCharacter().subscribe((character: any) => {
console.log(character)
this.http.get(character.homeworld).subscribe((homeworld: any) => {
this.loadedCharacter = character;
this.loadedCharacter.homeworld = homeworld.name;
this.http.get(character.species[0]).subscribe((species: any) => {
this.loadedCharacter.species = species.name;
this.makeQuestions();
});
});
});
SWAPI example json object:
{
"birth_year": "19 BBY",
"eye_color": "Blue",
"films": [
"https://swapi.co/api/films/1/",
...
],
"gender": "Male",
"hair_color": "Blond",
"height": "172",
"homeworld": "https://swapi.co/api/planets/1/",
"mass": "77",
"name": "Luke Skywalker",
"skin_color": "Fair",
"created": "2014-12-09T13:50:51.644000Z",
"edited": "2014-12-10T13:52:43.172000Z",
"species": [
"https://swapi.co/api/species/1/"
],
"starships": [
"https://swapi.co/api/starships/12/",
...
],
"url": "https://swapi.co/api/people/1/",
"vehicles": [
"https://swapi.co/api/vehicles/14/"
...
]
}
1 Answer
1
You are on the right track there and almost had it. Species is an array, so you would need another forkJoin
in there as well in case there is more than one species type:
forkJoin
return this.http.get(characterUrl)
.pipe(
mergeMap((character: any) => {
return forkJoin(
// Get the homeworld
this.http.get(character.homeworld),
// Another forkJoin for the species
forkJoin(
character.species.map(type => {
return this.http.get(type)
})
)
).pipe(
// Transform to a consumable object
map(d => {
return {
character: character,
homeworld: d[0],
species: d[1]
}
})
)
})
)
As an example, this will return an object with the following properties:
character: Object
homeworld: Object
species: Array[1]
Here is a StackBlitz demo
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
Comments
Post a Comment