$ apply vs $ digest em teste diretivo


98

Se eu tiver uma diretiva que responde ao status de um atributo específico no escopo e quiser alterar esse atributo em meu teste e verificar se ele responde corretamente, qual é a melhor maneira de fazer essa alteração?

Eu vi esses dois padrões:

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

e

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

Qual é a diferença entre eles, qual é o melhor e por quê?

Respostas:


206

scope.$digest()irá disparar observadores no escopo atual e em todos os seus filhos também. scope.$applyirá avaliar a função passada e executar $rootScope.$digest().

O primeiro é mais rápido, pois precisa avaliar os observadores para o escopo atual e seus filhos. O segundo é mais lento, pois precisa avaliar os observadores para$rootScope e todos os seus escopos filho.

Quando ocorre um erro em um dos inspetores e você o usa scope.$digest, ele não é tratado por meio do $exceptionHandlerserviço, portanto, você mesmo precisa tratar a exceção. scope.$applyusa um try-catchbloco internamente e passa todas as exceções para $exceptionHandler.


1
Irá $digesttambém ser chamados filhos do escopo?
pilau

15
Isso pode ser enganoso. $digestnão dispara observadores apenas no escopo atual, mas também em todos os seus filhos.
tasseKATT

@tasseKATT, acho que captei o que seu comentário está sugerindo.
activedecay

12

Como a própria documentação menciona, o ciclo $ digest é executado a qualquer momento $scope.$apply. De acordo com o guia do desenvolvedor sobre o escopo

Depois de avaliar a expressão, o método $ apply executa um $ digest. Na fase $ digest, o escopo examina todas as $ watch expressões e as compara com o valor anterior.

E de acordo com a documentação da API de escopo

Normalmente você não chama $ digest () diretamente nos controladores ou nas diretivas. Em vez disso, uma chamada para $ apply () (normalmente de dentro de uma diretiva) forçará um $ digest ().

Portanto, você não deve chamar explicitamente $digest, seu $applymétodo de chamada acionaria um ciclo de resumo.


8
isso não é verdade, pois digest é suficiente para a maioria dos casos em que apenas o escopo atual e seus filhos precisam ser avaliados. é verdade que $ scope. $ apply chama $ digest internamente, mas é muito importante lembrar que ele acabará chamando $ rootScope. $ digest () e, portanto, muito pesado
Srivathsa Harish Venkataramana
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.