$ apply vs $ Digest beim Testen von Anweisungen

98

Wenn ich eine Direktive habe, die auf den Status eines bestimmten Attributs im Bereich reagiert, und ich dieses Attribut in meinem Test ändern und überprüfen möchte, ob es korrekt reagiert, wie kann ich diese Änderung am besten durchführen?

Ich habe beide Muster gesehen:

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

und

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

Was ist der Unterschied zwischen ihnen und was ist besser und warum?

Daniel Roseman
quelle

Antworten:

206

scope.$digest()wird Beobachter auf das aktuelle Zielfernrohr und auch auf alle seine Kinder feuern. scope.$applywird die übergebene Funktion auswerten und ausführen $rootScope.$digest().

Der erste ist schneller, da Beobachter den aktuellen Umfang und seine Kinder bewerten müssen. Der zweite ist langsamer, da er die Beobachter $rootScopeund alle untergeordneten Bereiche bewerten muss .

Wenn bei einem der Beobachter ein Fehler auftritt und Sie ihn verwenden scope.$digest, wird er nicht über den $exceptionHandlerDienst behandelt, sodass Sie die Ausnahme selbst behandeln müssen. scope.$applyverwendet try-catchintern einen Block und übergibt alle Ausnahmen an $exceptionHandler.

Tadeusz Wójcik
quelle
1
Wird $digestauch die Kinder des Oszilloskops angerufen?
Pilau
15
Dies kann irreführend sein. $digestfeuert nicht nur Beobachter auf den aktuellen Umfang, sondern auch auf alle seine Kinder.
TasseKATT
@tasseKATT, ich glaube, ich habe erfasst, was Ihr Kommentar vorschlägt.
Activedecay
12

Wie in der Dokumentation selbst erwähnt, wird der $ Digest-Zyklus jederzeit ausgeführt $scope.$apply. Gemäß Entwicklerhandbuch zum Umfang

Nach dem Auswerten des Ausdrucks führt die $ apply-Methode einen $ Digest durch. In der $ Digest-Phase untersucht der Bereich alle $ watch-Ausdrücke und vergleicht sie mit dem vorherigen Wert.

Und gemäß der Scope API- Dokumentation

Normalerweise rufen Sie $ Digest () nicht direkt in Controllern oder Direktiven auf. Stattdessen erzwingt ein Aufruf von $ apply () (normalerweise innerhalb einer Direktive) einen $ digest ().

Sie sollten also nicht explizit aufrufen $digest, da Ihre aufrufende $applyMethode einen Digest-Zyklus auslösen würde.

Chandermani
quelle
8
Dies trifft nicht zu, da die Verdauung in den meisten Fällen ausreicht, in denen nur der aktuelle Umfang und seine Kinder bewertet werden müssen. Es ist wahr, dass $ scope. $ apply $ Digest intern aufruft, aber es ist sehr wichtig, sich daran zu erinnern, dass es letztendlich $ rootScope aufruft. $ Digest () und daher sehr schwer
Srivathsa Harish Venkataramana