I have a problem with Angular and Promises I don't understand.
This is my html:
<div>Is Ready? {{isReady}}</div>
<div *ngIf="isReady">Show this</div>
<div *ngIf="!isReady">Show that</div>
This is my TS file:
isReady: boolean = false;
constructor(
private myService: MyService){
await this.giveMeSlowData();
}
async giveMeSlowData() : Promise<void>{
console.log(await this.myService.getResult());
this.isReady = await this.myService.getResult();
}
Usually everything in this {{}} in HTML changes as soon as the variable in TS file. But not now. I can see console log after 5-6 seconds, but the HTML doesn't change. Why?
Thanks anyone!
CodePudding user response:
Whay are calling this.myService.getResult() twice ? try this :
async giveMeSlowData() : Promise<void>{
this.isReady = await this.myService.getResult();
console.log(this.isReady);
}
CodePudding user response:
There are a few reasons why this never completes yet you get your console log.
Actual problem
You have an async
method that never returns anything. That leaves the Promise
hanging forever. Since await
is called on the hung Promise
in the constructor, the component will never finish initializing. You can test this by adding a log statement in an ngOnInit
.
Recommendations
I would strong encourage you to switch to using an Observable as that is the standard practice in Angular world. A lot of things with component destruction is handled automatically for you that way. You can even do this without needing to change any logic of
MyService
which can be convenient if that must remain as aPromise
-based class.All initialization logic should be handled in an
ngOnInit
method, not in the constructor.I would encourage you to switch to using the
async
pipe in the template on all of this.
Solution
Here's how that all would come together.
slow-data.component.ts
:
isReady: Subject<boolean> = new BehaviorSubject(false);
constructor(
private myService: MyService,
) {
}
ngOnInit(): void {
giveMeSlowData();
}
giveMeSlowData(): void {
from(this.myService.getResult()).subscribe(isReady);
}
slow-data.component.html
<div>Is Ready? {{isReady | async}}</div>
<div *ngIf="isReady | async">Show this</div>
<div *ngIf="!(isReady | async)">Show that</div>