Breakup the Operations
One of the things to do is breakup the operations by chaining them.
$http.post('myBackend.php', someData)
.then (function onFulfilled (response) {
$scope.someDataToPopulateDOMwith = response.data;
return response;
}).then (function onFulfilled2 (response) {
doStuffWithDOMElements();
});
This allows the $q
service to execute a digest cycle before invoking the second fulfillment handler. The AngularJS framework needs to do a digest cycle so the watch handlers for the ng-repeat
directive have an opportunity update the DOM. The ng-repeat
directive needs to finish updating the DOM before the doStuffWithDOMElements
function can safely manipulate the DOM.
Use $timeout
Service
Avoid using the raw browser setTimeout
function, instead use the $timeout
service. The AngularJS $q
service then automatically does digest cycles.
Since the $timeout
service returns promises, it can be used for chaining.
$http.post('myBackend.php', someData)
.then (function onFulfilled (response) {
$scope.someDataToPopulateDOMwith = response.data;
return response;
}).then (function onFulfilled2 (response) {
//return $timeout promise
return $timeout(function(){return response}, 1000);
}).then (function onFulfilled3 (response) {
doStuffWithDOMElements();
});
Because calling the then
method of a promise returns a new derived promise, it is easily possible to create a chain of promises. It is possible to create chains of any length and since a promise can be resolved with another promise (which will defer its resolution further), it is possible to pause/defer resolution of the promises at any point in the chain. This makes it possible to implement powerful APIs.1
Re-factor the Design
The AngularJS is a MVW* framework.
Avoid manipulating HTML DOM programmatically: Manipulating HTML DOM is a cornerstone of AJAX applications, but it's cumbersome and error-prone. By declaratively describing how the UI should change as your application state changes, you are freed from low-level DOM manipulation tasks. Most applications written with Angular never have to programmatically manipulate the DOM, although you can if you want to.2
Look into modeling what the doStuffWithDOMElements()
function does and creating custom directives to watch that model and update the DOM. This fits better with the AngularJS framework and will avoid these timing issues.