Reputation: 823
I'm new in Angular and now trying to learn it and have a problem. I have a simple service method which I call in another component. But I have strange order of execution:
You can see it in console browser:
Could anyone please explain how does it work? And how to fix it?
Upvotes: 1
Views: 5258
Reputation: 775
This has to do with the fact, that I/O operations are usually designed to be non-blocking. Setting up a request via http.get
is such a non-blocking operation. It takes time to complete and in the meanwhile your other code will run first.
You wouldn't want your app to freeze while it waits for a 5sec response from the server would you?
If you would like to display your result you may just split up your logic for that, like so:
_weatherForecast: WeatherForecast = null;
calculateWeatherForecast() {
this.http.get<WeatherForecast>(this._url).subscribe((data) => {
this._weatherForecast = data;
});
}
getWeatherForecast() {
return this._weatherForecast;
}
That way you may fetch your data independently from displaying them. Angular would detect the change of your variable and render the result. In your template you would just do:
<div>{{getWeatherForecast()}}</div>
That has the advantage that you won't fetch new data from the server, every time you want to display your weatherForecast
. It gives you more control over how often and when to ask your server for new data.
Edit:
As it was pointed out in the comments, the code will break, when trying to access a property (in that case summary
) on _weatherForecast
. If you would like to avoid that you have two options:
<div>{{ getWeatherForecast()?.summary }}</div>
getWeatherForecast() {
if(this._weatherForecast) {
return this._weatherForecast.summary;
}
}
You may also change the method getWeatherForecast()
to get weatherForecast()
. That way you may access it in your template like a property of your component, like so:
<div>{{ weatherForecast?.summary }}</div>
Upvotes: 1
Reputation: 330
The code outside the subscribe() method is always executed last. It doesn't matter if it's before or after if it's at the same level.
To fix it instead of doing a "get" method, use a global variable and initialize it on ngOnInit().
weather :WeatherForecast = null;
ngOnInit(){
this.http.get<WeatherForecast>(this._url).subscribe(
data => {
this.weather = data;
}
)
}
I suggest you to organize http calls between component.ts and a service to make it more independent.
Upvotes: 1
Reputation: 4378
There are 2 portions in your code:
Synchronous
The part outside of your subscribe method is synchronous i.e. it will execute instantly following your program flow of execution.
Asynchronous
The part inside your subscribe method is asynchronous i.e. it will only execute when the get request is completed ( response is returned ).
Explanation
Now since the http request to the server will take some time. so the synchrouns part will continue its execution and it will not wait for get request to complete. so the console.log
[1] will execute first.
The line
return this.weatherForcast
is executed next due to synchronous code and return undefined which causes error inside console [2]
Your subscribe
function is then called at some point later in time (when get request is completed) and data is shown in console [3].
Upvotes: 1