angular waiting for a method to finish or a variable to be initialized

16,158

Solution 1

remove initializeData() from constructor and do something like this:

public async initializeData()
{
   this.optyList = await this.dataService.getObjectData('opportunities').toPromise();
   this.leadList = await this.dataService.getObjectData('leads').toPromise();
}


async ngOnInit() 
{
     await initializeData();

     for(let lead of this.dataStore.leadList){
         if(lead.accepted == false)
         this.newLeadsList.push(lead)
     }  
}  

I made code from head so it can have some bugs - may be async should be also before function ngOnInit()... check this.

Async-await-toPromise make that your asynchronous function behaves as synchronous function... and JS wait until your toPromise finish before execute another promise...

UPDATE

If I understand you right: you wanna call your service "DataStoreService.initializeData()" once and use it in future in other components (without calling initializeData again) - ? - if yes then you need Service singleton (which can also use inside above async-await technique)

Solution 2

What you can utilize is observables, in this case a BehaviorSubject which you subscribe to and always emits if there is a subscriber. After making the initial request, just call next and all components that are subscribing will get the value... when it eventually arrives:

DataStoreService:

import {BehaviorSubject} from 'rxjs/BehaviorSubject';

// ...

leadList: LeadModel[]
leadList$ = new BehaviorSubject<LeadModel[]>([])

constructor(public dataService:DataService){
  this.initializeData()
}

initializeData() {
  this.dataService.getObjectData('leads')
    .subscribe((data) =>  {
      this.leadList = data;
      this.leadList$.next(this.leadList)
    })
}

Then in your components, subscribe to leadList$:

leadList = <LeadModel[]>[];

ngOnInit() {
  this.dataStore.leadList$.subscribe(data => {
    this.leadList = data;
    // do your magic here :)
  })
}

Then remember to unsubscribe when component is destroyed!

Share:
16,158
Vik
Author by

Vik

http://www.oracle.com/innovation/innovator-vivek-kumar.html http://adfjsf.blogspot.com http://www.linkedin.com/vikceo http://www.twitter.com/vikceo

Updated on June 18, 2022

Comments

  • Vik
    Vik almost 2 years

    I have a service used as a local data store to share data across the app. This service makes a few rest calls in the beginning to initialize some data. It look like this:

    Injectable()
    export class DataStoreService {
         leadList: LeadModel[]
         optyList: ContactModel[]
    
         constructor(public dataService:DataService){
             this.initializeData()
         }
    
         initializeData() {
    
             this.dataService.getObjectData('opportunities').subscribe(
                 (data) =>  this.optyList = data
             )
    
             this.dataService.getObjectData('leads').subscribe(
                 (data) =>  this.leadList = data
             )
         }
    }
    

    I have a component page where I do below:

    ngOnInit() {
         for(let lead of this.dataStore.leadList){
                 if(lead.accepted == false)
                  this.newLeadsList.push(lead)
         }
    }
    

    It is very obvious that if initialize data fails to finish the leadList may be undefined and this ngOnInit for loop will crash as well. So, how do I wait in the ngOnInit until initializeData finishes?