AngularJS: $evalAsync против $timeout

Я использую AngularJS в течение некоторого времени, и нашел, что нужно использовать $timeout время от времени (кажется, обычно init плагин jQuery).

В последнее время я пытаюсь получить лучшее и более глубокое понимание цикла дайджеста, и я наткнулся на $evalAsync.

Кажется, что эта функция дает аналогичные результаты $timeout, только вы не даете ей задержки. Каждый раз, когда я использовал $timeout, он был с задержкой 0, так что теперь мне интересно, если бы я использовал $evalAsync вместо этого.

Есть ли фундаментальные различия между ними? В каких случаях вы бы использовали один над другим? Я хотел бы получить лучшее представление о том, когда использовать тот.

Ответ 1

Недавно я ответил на этот вопрос: fooobar.com/questions/18452/... (Этот ответ ссылается на некоторые обмены github с Misko.)

Подводя итог:

  • если код поставлен в очередь с помощью $evalAsync из директивы, он должен запускаться после того, как DOM был обработан Angular, но прежде чем браузер отобразит
  • если код поставлен в очередь с использованием $evalAsync с контроллера, он должен запускаться до того, как DOM будет обработан Angular (и до отображения браузером) - редко вы хотите этого
  • если код поставлен в очередь с использованием $timeout, он должен запускаться после того, как DOM был обработан с помощью Angular, и после отображения браузера (что может вызвать мерцание в некоторых случаях)

Ответ 2

Для тех, кто строит сложные приложения, имейте в виду, что на ваш выбор влияет производительность. Кроме того, я хотел бы завершить ответ Марка с более подробными техническими данными:

  • $timeout (обратный вызов) будет ждать выполнения текущего цикла дайджеста (т.е. angular обновить всю модель и DOM), тогда он выполнит свой обратный вызов - потенциально затрагивающий angular - затем запустите полный $apply в корневой области $scope и переименуйте все.

  • $evalAsync (обратный вызов), с другой стороны, добавит обратный вызов в текущий или следующий цикл дайджест. Это означает, что если вы находитесь в цикле дайджеста (например, в функции, вызываемой из некоторой директивы ng-click), это ничего не ждет, код будет немедленно выполнен. Если вы находитесь в асинхронном вызове, например a setTimeout, будет запущен новый цикл дайджеста ($apply).

Таким образом, с точки зрения производительности всегда лучше называть $evalAsync, если для вас не важно, чтобы представление было актуальным до выполнения вашего кода, например, если вам нужны acces для некоторого атрибута DOm, такого как ширина элементов и т.п.

Если вы хотите получить более подробную информацию о различии между $timeout, $evalAsync, $digest, $apply, я приглашаю вас прочитать мой ответ на этот другой вопрос: fooobar.com/info/12065/...

Также не забудьте прочитать документацию:

$evalAsync не дает никаких гарантий относительно того, когда будет выполняться выражение, только следующее:

  • он будет выполняться после функции, которая запланировала оценку (желательно до рендеринга DOM).
  • после выполнения выражения будет выполняться хотя бы один цикл $digest.

Примечание: , если эта функция вызывается за пределами цикла $digest, будет запланирован новый цикл $digest. Тем не менее, рекомендуется всегда вызывать код, который изменяет модель из $apply call. Это включает код, оцененный через $evalAsync.