I'm trying to create an Angular (v19) app, which basically consumes an API and uses the responses to render the app's UIs. A pretty standard scenario. The only thing more “audacious” is that I would like to initialize a variable during the construction of the app, so that it is available to other components.
But the problem is that the service, which I placed into the constructor, doesn't receive the results before the Angular starts the other stages of the lifecycle. The same problem is described here, here and others.
My first step was to create a service to consume the API:
frequency.service.ts
fetchMostRecent(): Observable<Frequency> {
console.log('FrequencyService.fetchMostRecent');
return this.httpClient.get<Frequency>(this.baseUrl + '/availability');
}
And in my component I'm trying to use some of the solutions suggested (toPromise/firstValueFrom/async) in the posts mentioned:
app.component.ts
export class AppComponent implements OnInit {
constructor(private frequencyService: FrequencyService) {
console.log('constructor');
this.fetchMostRecentAsync();
}
ngOnInit() {
console.log('ngOnInit');
}
async fetchMostRecentAsync() {
console.log('fetchMostRecentAsync');
this.mostRecent = await firstValueFrom(this.frequencyService.fetchMostRecent()).then(value => {
return value);
});
console.log('fetchMostRecentAsync: ' + this.mostRecent);
}
}
However, the ngOnInit
is still executed before the request into the constructor
is completed. In the console, the call sequence looks like this:
So my question is how I should implement this correctly...
You can use a resolver, which will do exactly what you want. But it blocks rendering of the component. Hence I am suggesting the below method.
We can call the API call on ngOnInit
and once the API call is completed, we can call the initialize
method which contains the initialization code, that depends on the API call. This method does not block the component from loading and also waits for the API call completion.
export class AppComponent implements OnInit {
constructor(private frequencyService: FrequencyService) {
console.log('constructor');
}
ngOnInit() {
this.fetchMostRecentAsync();
}
async fetchMostRecentAsync() {
console.log('fetchMostRecentAsync');
this.mostRecent = await firstValueFrom(this.frequencyService.fetchMostRecent())
console.log('fetchMostRecentAsync: ' + this.mostRecent);
this.initialize();
}
initialize() {
// ...ngOnInit Logic goes here!
}
}