The code block below waits for a timeout, then performs an HTTP request with a promise, then changes an Angular Material scope variable based on the response. It is called during with an ng-change
on an input field. I also have an element with ng-hide="showStuff"
in my HTML, and obviously, when $scope.showStuff
becomes false, I want it to disappear right away. Unfortunately, it doesn't actually disappear until I select something else in the DOM.
I've used promises before to change things in the DOM, and those work fine. Why doesn't the DOM update on its own, and how do I work around it?
$scope.checkSomething = function() {
// Use a timeout to prevent a checks from going off too rapidly
if (queryTimeout) {
clearTimeout(queryTimeout);
}
queryTimeout = setTimeout(function() {
bluebird.bind({}).then(function() {
return makeHttpRequest();
}).then(function(res) {
$scope.showStuff = res.data.length > 0;
})
}, 500);
}
Use the $timeout
service, it returns a promise that is integrated with the AngularJS execution context and its digest cycle:
$scope.checkSomething = function() {
// Use a timeout to prevent a checks from going off too rapidly
if (queryTimeout) {
$timeout.cancel(queryTimeout);
}
queryTimeout = $timeout(function() {
return makeHttpRequest();
}, 500);
queryTimeout.then(function(res) {
$scope.showStuff = res.data.length > 0;
})
}
This will delay execution of makeHttpRequest
by 500 milliseconds. The $timeout Service returns a promise that be used to resolve the data from the server.
AngularJS modifies the normal JavaScript flow by providing its own event processing loop. This splits the JavaScript into classical and AngularJS execution context. Only operations which are applied in the AngularJS execution context will benefit from AngularJS data-binding, exception handling, property watching, etc.
By using the AngularJS $timeout service, the wrapped setTimeout
will be executed in the AngularJS execution context.
For more information, see