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

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

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

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

и

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

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

Ответ 1

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

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

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

Ответ 2

Как указывается сама документация, цикл $digest формируется в любое время $scope.$apply. В соответствии с руководством разработчика на scope

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

И в соответствии с API-интерфейсом Scope API

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

Поэтому вы не должны явно вызывать $digest, вы вызываете метод $apply, вызывая цикл дайджеста.