I have two angular service calls in which service call 2 should be made on the result of an value from the 1st service call. But my code is not hitting the second service call at all. Please find the code snippet below.
ngOnInit(): void { let personId: string = this._activatedRoute.snapshot.params['id'];
this._personService.getPersonById(personId)
.then(person => this.person = person);
console.log(this.person); --prints undefined but displays data within the html correctly.
if (this.person) {
this._teamService.getTeamById(this.person.teamId)
.then(teamData => this.team = teamData);
}
}
Add an await to your _personService.getPersonById since it returns a Promise.
The console.log will only be hit after the preceding await is complete.
public async ngOnInit() {
await this._personService.getPersonById(personId)
.then(person => this.person = person)
.catch(err => console.log(err));
console.log(this.person);
if (this.person) {
await this._teamService.getTeamById(this.person.teamId)
.then(teamData => this.team = teamData)
.catch(err => {
// note curlys allow multiple statments.
// do work with error, log it etc..
}
}
}
As to why you see value in HTML and not console. HTML Data binding will show result of Promise as soon as it has the value. The console.log is being called immediately(some ms) after getPersonById and when not awaiting, it does not have the value at that exact moment..
This is how to accomplish the above by nesting the functions. Note the async person
.
public async ngOnInit() {
await this._personService.getPersonById(personId)
.then(async person => {
// To Use await inside .then, add async like above
this.person = person;
await this._teamService.getTeamById(this.person.teamId)
.then(teamData => this.team = teamData)
.catch(err => console.log(err) );
})
.catch(err => console.log(err));
console.log(this.person);
When you call a function that returns a promise, the then will be called after the first promise is resolved.. And subsequent .thens(you can add them). The thens always run synchronously.. Too much of this is called 'chaining' and is perceived as bad design. Thens are sequential/synchronous no matter if you use await or not.
If you want the outter functions to wait( or 'block') so as to run synchronously as well, you await them as well.
Last Edit: I suggest using the following copied from another SO answer to learn about async/await.
Using:
public delay(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms));
}
Call the following and note the order of the output.. Add and change awaits to learn how it behaves.
public async someFcn() {
console.log('1');
this.delay(2000)
.then(x => console.log('2'));
console.log(3)
await this.delay(1000)
.then(x => console.log('4')
.then(x => console.log('5');
console.log('Done');
}