Antoine Esteve Antoine Esteve - 6 months ago 13
AngularJS Question

AngularJS digest postDigestQueue

One of our page is very heavy. To decrease our watcher count and to accelerate the angular digest cycle we are using a lot the On-Time-Binding syntax

::
. We are also using angular-bind-notifier to avoid unnecessary watchs over our expressions on this page.

This strategy allowed us to reduce the angular digest cycle considerably.

But this strategy has one down side: It uses the
$$postDigest
(
postDigestQueue
) to
unwatch
the expression after it has been evaluated successfully.

So what ?

At the end of the digest, angular will run through the
postDigestQueue
. As we used a lot of On-Time-Binding expressions, our
postDigestQueue
can grow up to more than 100 000 queued tasks.

The problem is that angular uses the following code to loop over the queue:

while (postDigestQueue.length) {
try {
postDigestQueue.shift()();
} catch (e) {
$exceptionHandler(e);
}
}



The shift method removes the element at the zeroeth index and shifts
the values at consecutive indexes down, then returns the removed
value.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift


Yes,
Array.prototype.shift()
is a very expensive call when there is a lot of elements in the array.

Our digest cycle will sometimes take more than 20 seconds because of that.

When we change the previous code with the following one, it is way faster:

for (var i = 0; i < postDigestQueue.length; i++) {
try {
postDigestQueue[i]();
} catch (e) {
$exceptionHandler(e);
}
}
postDigestQueue.length = 0;


Is there a reason why they did that ?
Shouldn't we use that much the one time binding ?


I could see one reason: if a task add itself a need task in the queue. Is is possible ? (
$$postDigest
is a private queue) An answer would be to use
pop
instead of
shift
if the order of execution is not important, but is it ?

Edit: The order seems important because the
postDigestQueue
is used with the animations.


If anyone is interested in possible official follow-ups, I opened an issue on the issue tracker.

Answer

Angular team merged a perf improvement that will be in the next 1.5.x release : https://github.com/angular/angular.js/commit/cb2f8c0d75bde9ac91f4129e871ff4a8301871f3

That will speed up the digest cycles especially when you use a lot $$postDigest like angular-bind-notifier does.

Comments