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.