Как часто выполняется цикл дайджеста AngularJS?

при обсуждении достоинств AngularJS двусторонняя привязка данных часто рекламируется как основное преимущество Angular над другими фреймворками JS. глубже, документация предполагает, что этот процесс выполняется через грязную проверку, а не через меры, управляемые событиями. Сначала кажется, что цикл дайджеста работает, когда метод срабатывает в фоновом режиме с периодическими интервалами, проверяя все $watches во время каждого цикла. Однако, читая дальше, кажется, что дайджест-петля-это на самом деле вызваны rootScope.digest(), который в свою очередь спровоцирован $.apply, который, в свою очередь, запускается событием(!), например событие onClick, вызываемое через ng-click.

но, как это может быть? Я думал угловатый не использует change listeners. Так как же на самом деле работает цикл дайджеста? угловой автоматически запускает цикл дайджеста внутри или цикл дайджеста запускается событиями? если дайджест-цикл запущен автоматически, как часто он работает?


некоторые моменты уточнить:

  • Я не спрашиваю о том, как работает цикл дайджеста при ручной привязке к изменениям. В этом случае, если вы хотите заставить цикл дайджеста, вы можете сделать это, вызвав $.apply()
  • Я также не спрашиваю о том, как часто цикл дайджеста выполняется в ответ на события пользователя. Например, если ng-модель находится на поле ввода, Angular запустит цикл дайджеста, когда пользователь начнет печатать. Этот запутанная часть заключается в том, что для того, чтобы знать, что пользователь печатал, не использует угловой событие на основе onKeyUp где-то?
  • Я уже знаю, что существует предел 10 циклов max на дайджест-цикл. Мой вопрос меньше о количестве циклов на цикл дайджеста, а скорее о количестве циклов дайджеста, которые выполняются, скажем, в секунду.
  • бонусные вопросы: как цикл дайджеста относится к циклу событий JavaScript? Периодически ли цикл событий JS выполняется в фон? Является ли цикл дайджеста тем же, что и цикл событий, но только в "угловом контексте"? Это совершенно разные идеи?

3 ответов


запускаются угловые дайджесты - они не происходят через опрос.

код выполняется, после завершения кода angular запускает дайджест.

пример:

 element.on('click', function() {
     $scope.$apply(function() { 
         // do some code here, after this, $digest cycle will be triggered
     });
 });

Angular также вызовет $ digest после фазы компиляции / ссылки:

Compile > Link > Digest

а сколько циклов дайджеста запускается? Это зависит от того, как скоро переменных stabalise. Обычно для этого требуется не менее 2 циклов.


короткий прямой ответ на главный вопрос "нет", угловой не автоматически запускает цикл дайджеста.

TL; DR ответ:

Digest loop предназначен для запуска грязной проверки моделей POJO, связанных с экземплярами угловой области, поэтому его нужно запускать только тогда, когда модель может быть изменена. В одностраничном веб-приложении, работающем внутри браузера, следующие действия / события могут привести к изменению модели

  1. событий DOM
  2. ответы XHR стрельбы ответами
  3. изменение местоположения браузера
  4. таймеры (setTimout, setInterval), запускающие обратные вызовы

соответственно, угловой триггер digest loop at, например

  1. входные директивы+ngModel, ngClick, ngMouseOver и т. д.
  2. $ http и $ resource
  3. $расположение
  4. $тайм-аут

попробуйте ответить на эти бонусные вопросы от меня понимание:

  1. директива ngModel часто используется с директивами углового ввода (текст, выбор и т. д.) Вместе, и позже будут прослушивать события "изменения" и вызывать API $setViewValue, предоставляемые ngModelController, чтобы синхронизировать значение dom. Во время процесса синхронизации ngModelController обязательно запустит цикл дайджеста.
  2. цикл дайджеста отличается от цикла событий JS, более поздняя концепция JS runtime (проверка большой визуализированной сессии https://www.youtube.com/watch?v=8aGhZQkoFbQ), которые запускаются против очереди событий и автоматически удаляют потребляемое событие из очереди, но цикл дайджеста никогда не удаляет часы из своего списка наблюдения, если вы явно не разматываете.
  3. количество циклов дайджеста в секунду зависит от эффективности всех обратных вызовов часов, выполняемых через цикл . Если какой-то плохой код занял одну секунду, чтобы закончить, то этот цикл дайджеста будет стоить больше 1 секунды.

Так некоторые ключевые практики для предотвращения угловых ошибок производительности

  1. обратный вызов Watch должен быть закодирован как можно проще / эффективнее, например, отсоединить сложный код алгоритма, например, рабочие потоки
  2. предварительно удалить часы, если он больше не используется
  3. предпочитают вызывать $scope.$digest () вместо $scope.$apply() если применимо, $digest() запускает только часть дерева областей и гарантирует, что модели, связанные с поддеревом, отражают вид. Но $apply () будет работать против всего дерева областей, он будет повторяться через больше часов.

Я считаю, что это то, что происходит. AngularJS сделал умное предположение, что изменения модели происходят только при взаимодействии с пользователем. Эти взаимодействия могут произойти из-за

  • активность мыши (перемещение, щелчок и т. д.)
  • активность клавиатуры (клавиша вверх, клавиша вниз и т. д.)

директивы AngularJS для соответствующих событий переносят выполнение выражения в $scope.$применить, как показано @pixelbits в его примере. Это приводит к циклу дайджеста.

там есть и другие события, где AngularJS запускает цикл дайджеста. $ timeout service и $interval service-два таких примера. Код, обернутый в эту службу, также приводит к циклу дайджеста для запуска. Возможно, есть некоторые другие события\службы,которые могут вызвать выполнение циклов дайджеста, но это основные.

именно по этой причине изменения модели вне углового контекста не обновляют часы и привязки. Поэтому нужно явно вызвать $scope.$применять. Мы делаем это все время при интеграции с плагинами jQuery.