$ apply vs $ digest при тестировании директив

98

Если у меня есть директива, которая отвечает на статус определенного атрибута в области видимости, и я хочу изменить этот атрибут в моем тесте и убедиться, что он отвечает правильно, что является лучшим способом сделать это изменение?

Я видел оба этих паттерна:

scope.$apply(function() {
    scope.myAttribute = true;
});

и

scope.myAttribute = true;
scope.$digest();

В чем разница между ними, что лучше и почему?

Дэниел Розман
источник

Ответы:

206

scope.$digest()уволит наблюдателей на текущем прицеле, а также на всех его дочерних объектах. scope.$applyоценит переданную функцию и запустит $rootScope.$digest().

Первый быстрее, так как он должен оценивать наблюдателей для текущей области и ее дочерних элементов. Второй медленнее, так как он должен оценивать наблюдателей $rootScopeи все его дочерние области.

Когда ошибка возникает в одном из используемых вами наблюдателей scope.$digest, она не обрабатывается через $exceptionHandlerслужбу, поэтому вам нужно обработать исключение самостоятельно. scope.$applyиспользует try-catchблок внутри и передает все исключения в $exceptionHandler.

Тадеуш Вуйчик
источник
1
Будет $digestтакже призвал детей прицела?
плов
15
Это может ввести в заблуждение. $digestне только увольняет наблюдателей на текущем прицеле, но и на всех его дочерних объектов.
tasseKATT
@tasseKATT, я думаю, что понял то, что предлагает ваш комментарий.
activedecay
12

Поскольку в самой документации упоминается, цикл $ digest выполняется каждый раз, когда вы это делаете $scope.$apply. Согласно руководству разработчика по объему

После вычисления выражения метод $ apply выполняет дайджест $. На этапе $ digest область видимости проверяет все выражения $ watch и сравнивает их с предыдущим значением.

И согласно документации Scope API

Обычно $ digest () не вызывается непосредственно в контроллерах или в директивах. Вместо этого вызов $ apply () (обычно из директив) вызовет $ digest ().

Таким образом, вы не должны явно вызывать $digest, вызывающий $applyметод вызовет цикл дайджеста.

Чандермани
источник
8
это неверно, поскольку дайджеста достаточно в большинстве случаев, когда нужно оценивать только текущую область и ее дочерние элементы. это правда, что $ scope. $ apply вызывает $ digest внутри себя, но очень важно помнить, что в конечном итоге он вызовет $ rootScope. $ digest () и, следовательно, очень тяжелый
Шриватса Хариш Венкатарамана