When working with directives that do not involve any Promises, an alternative directive can be used to compile its element and then utilize $timeout without the need for dirty checks (setting the 3rd argument to false) within the $compile's callback function:
app.directive('measure', function () {
return {
controller: function ($scope, $element, $compile, $timeout, $window) {
$window.start = new Date().getTime();
// ensure compilation only happens once
if (!$window.done) {
console.log('BEGINNING MEASUREMENT');
$window.done = true;
$compile($element)($scope, function(clonedElement, scope) {
var timer = $timeout(function () {
console.log('ENDING MEASUREMENT: ' + (new Date().getTime() - $window.start) + 'ms');
$timeout.cancel(timer);
}, 0, false);
});
}
}
};
})
For directives involving Promises, measurement can be done by using $timeout without dirty checks but called within the then block of the last Promise:
app.directive('someOtherDir', function () {
return {
template: '<div ng-repeat="item in vm.data"><img ng-src="{{ item.thumbnailUrl }}" title="{{ item.title }}"></div>',
controller: function ($http, $timeout, $window) {
console.log('STARTING MEASUREMENT');
$window.start = new Date().getTime();
var vm = this;
$http.get('data.json').then(function (res) {
vm.data = res.data;
var timer = $timeout(function () {
console.log('ENDING MEASUREMENT: ' + (new Date().getTime() - $window.start) + 'ms');
$timeout.cancel(timer);
}, 0, false);
});
},
controllerAs: 'vm'
};
});
Here is a playground plunker showcasing these directives http://plnkr.co/edit/McWOeF7rZ7ZYKnDWafy6?p=preview. You can comment/uncomment the two directives and experiment with increasing the value of i within the someDir directive:
for (var i = 0; i < 20; i++) {
vm.dates.push({
timestamp: i * 1000 * 60 * 60 * 24,
label: new Date(i * 1000 * 60 * 60 * 24).toString()
});
}
Try values like 200, 2000...