Reputation: 163
I have this issue with setInterval in an Angular 4 component. It seems like the scope is wrong and not updating the component as expected. I've read around that arrow functions are the solution to maintaining the scope here of the component.
It appears that the role is definitely set (results are updated in the template file as expected) and the setInterval does in fact stop running via what I assume is the call to clearInterval(). However, this.loadingActions which I'd like to be set to false (initialized as true) is not properly updated. If I debug in that block this.loadingActions member on the component is undefined whereas the console.log(this.loadingActions) prints false and the UI itself remains not updated.
roleSetup() is called via ngOnInit()
roleSetup() {
this.fetchRole = setInterval(() => {
this.role = this.userDataService.getUserModel().role;
}, 1000)
if (this.role !== "") {
console.log("hullo");
this.loadingActions = false;
console.log(this.loadingActions);
clearInterval(this.fetchRole);
console.log(this);
debugger;
}
console.log(this.loadingActions);
console.log(this.role);
}
I've also tried something like this, which I know is improper but still no luck with the scope
this.fetchRole = setInterval(() => {
this.role = this.userDataService.getUserModel().role;
if(this.role !== "") {
this.loadingActions = false;
}
}, 1000)
if (this.role !== "") {
clearInterval(this.fetchRole);
}
console.log(this.role);
console.log(this.loadingActions);
Upvotes: 1
Views: 178
Reputation: 473
I think what's happening is a timing issue.
setInterval
will run the passed function asynchronously. Therefore, all your code after setInterval
runs before the role is fetched, so the if statement checking if the role exists always evaluates to false
.
The reason it updates in the template is because Angular uses Zone.js, which is a library that alerts Angular after any browser event is done executing. (If you know angular.js, you can think of it as a tool which runs a digest cycle automatically after the setInterval
)
Without removing your polling for the role, you could simply move your logic into the setInterval
. That way, once the role is loaded, you can update the loadingActions
boolean.
roleSetup() {
this.fetchRole = setInterval(() => {
this.role = this.userDataService.getUserModel().role;
if (this.role !== "") {
this.loadingActions = false;
clearInterval(this.fetchRole);
}
}, 1000)
}
But it would probably be better if you could update your userDataService
to have a function which returns the role in terms of a promise:
roleSetup() {
this.userDataService.getUserRole().then(role => {
this.role = role;
this.loadingActions = false;
});
}
Without knowing how your application is loading the role, I don't know if this is possible, but it would certainly be cleaner if you could do it this way.
Upvotes: 2