Home > Blockchain >  Angular 2 - Property is undefined after subscription ended
Angular 2 - Property is undefined after subscription ended

Time:03-10

Using angular 2 - I have declared a public property which I am expecting to be populated with promise data object, using "ngOnInit" lifecycle method in order to send http request to my API.

in subscribe block I am assigning the property to the data received from the observable but then I want to log this property its appear as undefined outside the subscription but not undefined inside the subscription block which is odd behavior (am i missing something?) code below:

async ngOnInit(): Promise<any> {
  console.log(this.indexID);
  const elements = document.getElementsByClassName('footer-wrap');
  while (elements.length > 0){
    elements[0].parentNode.removeChild(elements[0]);
  }
  await this.landingService.getLandingDataById(this.indexID)
  .subscribe((res:any) => {
    this.landingData = res['data'][0];    
  });
  console.log(this.landingData); 
}

CodePudding user response:

await this.landingService.getLandingDataById(this.indexID)
.subscribe((res:any) => {
  this.landingData = res['data'][0];    
});

doesn't make sense. .subscribe returns a subscription. You can't await it. You can't await an observable, because it can trigger multiple times, but you can convert an observable to a promise, e.g. with firstValueFrom

async ngOnInit(): Promise<void> {
  console.log(this.indexID);
  const elements = document.getElementsByClassName('footer-wrap');
  while (elements.length > 0){
    elements[0].parentNode.removeChild(elements[0]);
  }
  const res = await firstValueFrom(this.landingService.getLandingDataById(this.indexID));
  this.landingData = res['data'][0];    
  console.log(this.landingData); 
}

its appear as undefined outside the subscription but not undefined inside the subscription block which is odd behavior

That's not odd. That's the expected behavior. this.landingData = res['data'][0]; is executed after console.log(this.landingData);. this.landingService.getLandingDataById(this.indexID) returns an asynchronous observable. You can remove async / await and move the console.log into the observer:

ngOnInit(): void {
  console.log(this.indexID);
  const elements = document.getElementsByClassName('footer-wrap');
  while (elements.length > 0){
    elements[0].parentNode.removeChild(elements[0]);
  }
  this.landingService.getLandingDataById(this.indexID)
  .subscribe((res:any) => {
    this.landingData = res['data'][0];  
    console.log(this.landingData);   
  });
}

CodePudding user response:

Ive tried to convert observable to promise , now the property is populated but template still cannot read it

async ngOnInit(): Promise<any> {
console.log(this.indexID);
const elements = document.getElementsByClassName('footer-wrap');
while (elements.length > 0){
  elements[0].parentNode.removeChild(elements[0]);
}
await this.landingService.getLandingDataById(this.indexID).toPromise().then((res:any) => {
  this.landingData = res['data'][0];
});
// .subscribe((res:any) => {
//   this.landingData = res['data'][0]; 
//   console.log(this.landingData);    
// });
console.log(this.landingData.indexPhoto);

}

  • Related