Одна из наших страниц очень тяжелая. Чтобы уменьшить количество наблюдателей и ускорить цикл angular digest, мы используем синтаксис On-Time-Binding ::
. Мы также используем angular-bind-notifier, чтобы избежать ненужных наблюдений за нашими выражениями на этой странице.
Эта стратегия позволила значительно сократить цикл дайджест angular.
Но эта стратегия имеет одну сторону: она использует $$postDigest
(postDigestQueue
) для unwatch
выражение после он был успешно оценен.
Итак, что?
В конце дайджеста angular будет выполняться через postDigestQueue
. Поскольку мы использовали много выражений On-Time-Binding, наш postDigestQueue
может вырасти до более чем 100 000 задач в очереди.
Проблема заключается в том, что angular использует следующий код для перебора очереди:
while (postDigestQueue.length) {
try {
postDigestQueue.shift()();
} catch (e) {
$exceptionHandler(e);
}
}
Метод сдвига удаляет элемент с нулевым индексом и сдвигает значения при последовательных индексах вниз, а затем возвращает удаленные стоимость.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift
Да, Array.prototype.shift()
- очень дорогостоящий вызов, когда в массиве много элементов.
Наш цикл дайджеста иногда занимает более 20 секунд из-за этого.
Когда мы меняем предыдущий код на следующий, он быстрее:
for (var i = 0; i < postDigestQueue.length; i++) {
try {
postDigestQueue[i]();
} catch (e) {
$exceptionHandler(e);
}
}
postDigestQueue.length = 0;
Есть ли причина, по которой они это сделали? Разве мы не должны использовать такую привязку?
Я мог видеть одну причину: если задача добавляет себе задачу в очередь. Возможно ли это? ($$postDigest
- приватная очередь). Ответ заключается в использовании pop
вместо shift
, если порядок выполнения не важен, но так ли?
Изменить: Порядок кажется важным, потому что postDigestQueue
используется с анимацией.
Если кто-то заинтересован в возможных официальных последующих действиях, я открыл проблему в трекере.