$ apply vs $ digest dans les tests de directives

98

Si j'ai une directive qui répond au statut d'un attribut particulier sur la portée et que je souhaite modifier cet attribut dans mon test et vérifier qu'il répond correctement, quelle est la meilleure façon de faire ce changement?

J'ai vu ces deux modèles:

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

et

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

Quelle est la différence entre eux, quel est le meilleur et pourquoi?

Daniel Roseman
la source

Réponses:

206

scope.$digest()lancera des observateurs sur la lunette actuelle, et sur tous ses enfants aussi. scope.$applyévaluera la fonction passée et exécutera $rootScope.$digest().

Le premier est plus rapide, car il doit évaluer les observateurs pour la portée actuelle et ses enfants. Le second est plus lent, car il doit évaluer les observateurs $rootScopeet toutes ses portées enfants.

Lorsqu'une erreur se produit dans l'un des observateurs et que vous utilisez scope.$digest, elle n'est pas gérée via le $exceptionHandlerservice, vous devez donc gérer l'exception vous-même. scope.$applyutilise un try-catchbloc en interne et transmet toutes les exceptions à $exceptionHandler.

Tadeusz Wójcik
la source
1
Sera $digestégalement appelé les enfants du télescope?
pilau
15
Cela peut être trompeur. $digestne tire pas seulement les observateurs sur la portée actuelle, mais aussi sur tous ses enfants.
tasseKATT
@tasseKATT, je pense avoir capturé ce que votre commentaire suggère.
activé le
12

Comme la documentation elle-même le mentionne, $ digest cycle est exécuté à chaque fois que vous le faites $scope.$apply. Selon le guide du développeur sur la portée

Après avoir évalué l'expression, la méthode $ apply effectue un $ digest. Dans la phase $ digest, l'étendue examine toutes les expressions $ watch et les compare avec la valeur précédente.

Et selon la documentation de l' API Scope

Habituellement, vous n'appelez pas $ digest () directement dans les contrôleurs ou dans les directives. Au lieu de cela, un appel à $ apply () (généralement à partir d'une directive) forcera un $ digest ().

Vous ne devez donc pas appeler explicitement $digest, votre $applyméthode d' appel déclencherait un cycle de résumé.

Chandermani
la source
8
ce n'est pas vrai car digest est suffisant pour la plupart des cas où seuls la portée actuelle et ses enfants doivent être évalués. il est vrai que $ scope. $ apply appelle $ digest en interne mais il est très important de se rappeler qu'il finira par appeler $ rootScope. $ digest () et donc très lourd
Srivathsa Harish Venkataramana