Antoine Esteve Antoine Esteve - 9 months ago 36
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
) to
the expression after it has been evaluated successfully.

So what ?

At the end of the digest, angular will run through the
. As we used a lot of On-Time-Binding expressions, our
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 {
} catch (e) {

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

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 {
} catch (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 ? (
is a private queue) An answer would be to use
instead of
if the order of execution is not important, but is it ?

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

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


Angular team merged a perf improvement that will be in the next 1.5.x release :

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