SGN SGN - 1 month ago 23
TypeScript Question

Angular 2 - Waiting for boolean to be true before executing service

I have an navigation menu that uses ng2-page-scroll module.

I scroll trough page using hashtag links.

The problem is that if i work cross routes, the data takes some time to load, so the service normally scrolls to my section, than the whole data loads, and the section of interest will not be on screen fold anymore, so the user needs to manully scroll to get to the section of interst. This makes the whole menu useless.

So I'm using EventEmitter in all sections, to set bools in the "scrollable" page, all good...

But i don't know how to wait for the

allDataLoaded
boolean to turn true.

I tried to use promises

This is how my code looks so far.

HTML of navigation menu component

<a [routerLink]="['']" [queryParams]="{ scrollTo: '#home' }">
<a [routerLink]="['']" [queryParams]="{ scrollTo: '#contact' }">
<a [routerLink]="['']" [queryParams]="{ scrollTo: '#about' }">


HTML of component using root segment

<componentOne (dataLoadedEvent)="homeLoaded = true; checkIfDataLoaded()"></componentOne>


TS of component using root segment

homeLoaded: boolean = false;
contactLoaded: boolean = false;
aboutLoaded: boolean = false;

allDataLoaded: boolean = false;

ngOnInit() {
// other code here
this.route.queryParams.forEach((params: Params) => {
if (params['scrollTo']) {
this.checkIfDataLoaded().then(() => {
this.scrollToSection(params['scrollTo']);
});
}
});
}

checkIfDataLoaded() {
if (this.homeLoaded && this.contactLoaded && this.aboutLoaded) {
//this.allDataLoaded = true;
return new Promise((resolve, reject) => {
resolve(true);
});
}
}


As Günter Zöchbauer answered here ( http://stackoverflow.com/a/40126194/3264998 ) for another questoin, the code will break with
TypeError: Cannot read property 'then' of undefined


TL;DR What is the proper way to use promises when waiting for a bool to turn true/false?

Answer

The problem is in your code, in particular in checkIfDataLoaded() method and not because you're working with booleans.

It obviously throws an error when the inner condition resolves to false because then the method returns undefined and therefore calling undefined.then(... raises an error.

Of course, I don't know what exactly checkIfDataLoaded() should do but if you want to chain .then() to its result then it always has to return a Promise.

Maybe something along these lines:

checkIfDataLoaded() {
    return new Promise((resolve, reject) => {
        if (this.homeLoaded && this.contactLoaded && this.aboutLoaded) {
            // Whatever logic goes here
            resolve(true);
        } else {
            resolve(false);
        }
    });
}

This way checkIfDataLoaded() always returns Promise while its internals can do whatever you need.