Reputation: 37
What I want to achieve: Make calls from component.ts to the service this.getMatches, in this.getMatches I have to make some API calls and work with the data I get before it gets pushed to the array
What I did: 1: The function runs and send "gameId" as an argument to the function this.getmatches. I get an array of every match with all data that I pushed to every single match 2: I was able to find a method that worked after many tries, but it failed when it returning to the array
The problem: Sometimes it returns the same match, I noticed it happens when I add the "swtichmap" operator.
Services.ts
@Injectable({
providedIn: 'root'
})
export class SummonerService {
constructor( private http:HttpClient ) { }
summonerName
dataMatch
matchParticipants
matchHistory = [];
getSummoner(summonerName,regionId){
this.summonerName = summonerName
return this.http.get(`http://localhost:3000/summName/${summonerName}/${regionId}` )
};
getMatches(gameId){
return this.http.get( `http://localhost:3000/match/${gameId}`
).pipe(
tap( (data:any) => {
console.log(data.match);
this.dataMatch = data.match
this.matchParticipants = data.match.participants
}) ,
switchMap( data => {
return this.http.get(`http://ddragon.leagueoflegends.com/cdn/10.5.1/data/en_US/summoner.json`)
}),
tap( (data:any) =>{
let spellsObj = data.data;
const spellsArray:Array<any>[] = [];
Object.keys(spellsObj).forEach( key =>{
let spell = spellsObj[key]
spellsArray.push(spell)
});
this.matchParticipants.forEach( participants => {
let spellId1:any = spellsArray.find( (spell:any) => spell.key === JSON.stringify(participants.spell1Id) );
let spellId2:any = spellsArray.find( (spell:any) => spell.key === JSON.stringify(participants.spell2Id) );
let spellId1Image = `http://ddragon.leagueoflegends.com/cdn/10.5.1/img/spell/${spellId1.id}.png`
let spellId2Image = `http://ddragon.leagueoflegends.com/cdn/10.5.1/img/spell/${spellId2.id}.png`
participants.spellId1Info = spellId1
participants.spellId2Info = spellId2
participants.spellId1Info.image = spellId1Image
participants.spellId2Info.image = spellId2Image
});
}),
map ( data =>{
return this.dataMatch
})
)};
I put part of the code, but I need to make more calls like this .
switchMap( data => {
return this.http.get(`http://x.json`)
}),
I don't know if the call here with the "switchmap" was done correctly either
Component.ts
onSubmit( ){
this.summ.getSummoner( this.summoner.name,this.summoner.regionId )
.pipe(
tap( (summoner:any) => this.matchHistory = summoner.matchHistory ),
concatMap( (summoner:any) => {
const observables = this.matchHistory
.map( element => this.summ.getMatches(element.gameId));
return forkJoin(observables)
}),
map( (matchesArray:any) => {
let gameIdArray = this.matchHistory.map( element => element.gameId)
this.matchesArray = matchesArray.sort((a, b) => {
return gameIdArray.indexOf(a.gameId) - gameIdArray.indexOf(b.gameId);
});
return matchesArray
})
) .subscribe();
Upvotes: 0
Views: 1021
Reputation: 421
switchMap
here looks pretty ok to me, if you are not sure about that, feel free to check out my blog post about this topic: https://dev.to/rxjs/about-switchmap-and-friends-2jmm.
If you want to make multiple requests you need to apply a combination operator within the switchMap
, probably either merge
or forkJoin
. The code could look like this:
switchMap( data => merge(
this.http.get(`http://x.json`),
this.http.get(`http://y.json`),
this.http.get(`http://z.json`)
)),
So the question is which of those you want to use:
You want to use merge when you don't really care if the other HTTP calls are already completed. You will get a new value emited after the switchMap every time one of those HTTP requests return a response and you will also only get that very response.
You want to use forkJoin when you care that all HTTP calls are completed before you go one. You will also get an Array of HTTP responses which you can use to continue the processing.
Upvotes: 1