$ Apply vs $ Digest w testowaniu dyrektywy

98

Jeśli mam dyrektywę, która reaguje na stan konkretnego atrybutu w zakresie i chcę zmienić ten atrybut w moim teście i sprawdzić, czy odpowiada poprawnie, jaki jest najlepszy sposób wprowadzenia tej zmiany?

Widziałem oba te wzorce:

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

i

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

Jaka jest między nimi różnica i co jest lepsze i dlaczego?

Daniel Roseman
źródło

Odpowiedzi:

206

scope.$digest()będzie strzelać obserwatorów do obecnego teleskopu, a także do wszystkich jego dzieci. scope.$applyoceni przekazaną funkcję i uruchomi $rootScope.$digest().

Pierwsza jest szybsza, ponieważ wymaga oceny obserwatorów pod kątem obecnego zakresu i jego dzieci. Drugi jest wolniejszy, ponieważ musi oceniać obserwatorów $rootScopei wszystkie jego zakresy podrzędne.

Gdy błąd wystąpi w jednym z obserwatorów i używasz scope.$digestgo, nie jest on obsługiwany przez $exceptionHandlerusługę, więc musisz samodzielnie obsłużyć wyjątek. scope.$applyużywa try-catchbloku wewnętrznie i przekazuje wszystkie wyjątki do $exceptionHandler.

Tadeusz Wójcik
źródło
1
Czy wezwie się $digesttakże dzieci lunety?
pilau
15
To może być mylące. $digestnie tylko strzela do obserwatorów z obecnego zakresu, ale także do wszystkich swoich dzieci.
tasseKATT
@tasseKATT, myślę, że uchwyciłem to, co sugeruje twój komentarz.
aktywny dzień
12

Jak sama dokumentacja wspomina, cykl $ strawienia jest wykonywany za każdym razem, gdy to zrobisz $scope.$apply. Zgodnie z instrukcją programisty dotyczącą zakresu

Po oszacowaniu wyrażenia metoda $ Apply wykonuje podsumowanie $. W fazie $ digest zakres sprawdza wszystkie wyrażenia $ watch i porównuje je z poprzednią wartością.

I zgodnie z dokumentacją Scope API

Zwykle nie wywołuje się $ digest () bezpośrednio w kontrolerach ani w dyrektywach. Zamiast tego wywołanie $ apply () (zazwyczaj z wnętrza dyrektyw) wymusi $ digest ().

Więc nie powinieneś jawnie wywoływać $digest, wywołanie $applymetody wywołałoby cykl podsumowania.

Chandermani
źródło
8
nie jest to prawdą, ponieważ skrót jest wystarczający w większości przypadków, w których należy ocenić tylko bieżący zakres i jego elementy podrzędne. to prawda, że ​​$ scope. $ zastosuj wywołania $ digest wewnętrznie, ale bardzo ważne jest, aby pamiętać, że zakończy się to wywołaniem $ rootScope. $ digest () i stąd bardzo ciężkie
Srivathsa Harish Venkataramana