I have a property in an Angular component, instantiated through a service inside async ngOnInit
:
txtItems: TextItems[];
constructor(private textItemService: TextItemService) {}
async ngOnInit() {
// await on promise
this.txtItems = await this.textItemService.getAllAsync();
}
where getAllAsync
returns a promise:
async getAllAsync(): Promise<TextItems[]> {
return await this.http.get<TextItems[]>(this.url).toPromise();
}
ngOnInit
runs asynchronously so that the page doesn't have to hang until items are loaded (which is a good thing), but sometimes this.txtItems
is accessed from the template before it has finished loading, which results in an exception.
I can make ngOnInit
not async
, but then the page will load slowly.
Should I use txtItems: Promise<TextItems[]>
or something like that, and then access it from everywhere using the async
pipe? What is the correct approach when waiting for async services?
This is a classic case of converting an observable to a promise without any substantiated advantages. And given that the output from the HTTP request is used only in the template, you could return the observable from service and use it's value in the template using async
pipe.
Service
getAllAsync(): Observable<TextItems[]> {
return this.http.get<TextItems[]>(this.url);
}
Component
public txtItems$: Observable<TextItems[]>;
constructor(private textItemService: TextItemService) {
this.txtItems$ = this.textItemService.getAllAsync(); // <-- no `await`, only assignment
}
Template
<ng-container *ngIf="(txtItems$ | async) as txtItems">
<!-- use `txtItems` -->
</ng-container>