I'm trying to hit one api to retrieve a specific string which is then stored in a variable and passed to another http api call but the problem is the api call that needs the argument runs and never sends the correct request. (noobie here btw)
here are the two calls, removed some personal info from it but it still makes sense.
async getMatches() {
return this.http.get('matchesUrl', {
headers: {
'Authorization': 'Bearer **'
}
})
}
async getMatchStats(matchId: string) {
return this.http.get(`specificMatchUrl/${matchId}/`, {
headers: {
'Authorization': 'Bearer **'
}
})
}
And here is my component:
import { Component, OnInit } from '@angular/core';
import {GetapiService} from '../getapi.service';
@Component({
selector: 'app-gamingpage',
templateUrl: './gamingpage.component.html',
styleUrls: ['./gamingpage.component.scss']
})
export class GamingpageComponent implements OnInit {
title = '';
wins = '';
totalMatches = '';
currentWinStreak = '';
latestMap = '';
matchId = '';
constructor(
private api: GetapiService
) { }
async ngOnInit() {
this.api.getPlayerStats().subscribe((data: any) => {
this.title = data['game_id'];
this.wins = data.lifetime['Wins']
this.totalMatches = data.lifetime['Matches']
this.currentWinStreak = data.lifetime['Current Win Streak']
});
(await this.api.getMatches()).subscribe((data: any) => {
this.matchId = data.items[0].match_id;
});
(await this.api.getMatchStats(this.matchId)).subscribe((data: any) => {
this.latestMap = data.rounds.round_stats['Map']
})
}
}
I thought that awaiting both calls would fix this because the getMatchStats won't run until getMatches is done and that matchId variable is stored. But when the call is made, the url is incorrect and doesn't contain the matchId. I've verified that console.log is showing it correctly so I must be doing something wrong but can't seem to figure out what. I'm looking at the similar questions but none seem to be doing the same thing as me... or at least what I understand. Thanks in advance.
CodePudding user response:
keep it simple :)
this.matchId = (await this.api.getMatches()).items[0].match_id;
this.latestMap = (await
this.api.getMatchStats(this.matchId)).rounds.round_stats['Map'];
CodePudding user response:
Not use async await, use switchMap rxjs operators
this.api.getMatches()).pipe(switchMap((data:any)=>{
this.matchId =data.items[0].match_id;
return this.api.getMatchStats(this.matchId)
})).subscribe((data: any) => {
this.latestMap = data.rounds.round_stats['Map'];
});
Angular is full plenty Observables, with rxjs operators we can transform / join /delay... observables. These oblige us to think in "async way", but really are great. The most important rxjs operators (but not all) are
- forkJoin: join several observables and wait until all are completed
- switchMap: transform one observable in another one that depend from the first
- map: transform a response of an Observable
- merge: create an observable that emit a value each time one of several observables emit one value
I know it's a bit complex, but it's necessary understand a bit about rxjs operators to use Angular
CodePudding user response:
Get your first call this.api.getMatches() in this strucure:
myObservable.subscribe(
x => console.log('Observer got a next value: ' x),
err => console.error('Observer got an error: ' err),
() => console.log('Observer got a complete notification')
);
Once you have done that put your second call in the onComplete statement
() => {
(await this.api.getMatchStats(this.matchId)).subscribe((data: any) => {
this.latestMap = data.rounds.round_stats['Map']
})
}
That sould do it. :)