Warum benutzt man if (! $ Scope. $$ phase) $ scope. $ Apply () ein Anti-Pattern?
Manchmal muss ich verwenden $scope.$apply
in meinem code und manchmal wirft es einen "digest bereits in progress" - Fehler. So begann ich einen Weg zu finden, um das gefunden und diese Frage: AngularJS : Vermeiden Sie den Fehler, $digest, die bereits im Gange beim Aufruf von $scope.$anwenden(). Aber in den Kommentaren (und auf den eckigen wiki) kann man Lesen:
Nicht tun, wenn (!$scope.$$phase) $scope.$apply(), bedeutet dies, dass Ihre $scope.$Anwendung (die) nicht hoch genug in den call-stack.
So, jetzt habe ich zwei Fragen:
- Warum genau ist das ein anti-pattern?
- Wie kann ich sicher verwenden $scope.$bewerben?
Andere "Lösung" um zu verhindern, dass "digest bereits in progress" - Fehler scheint zu sein, mit $timeout:
$timeout(function() {
//...
});
Ist, dass der Weg zu gehen? Ist es sicherer? Also hier die eigentliche Frage: Wie kann ich ganz beseitigen die Möglichkeit, ein "digest bereits in progress" - Fehler?
PS: ich bin nur die Verwendung von $scope.$gelten in nicht-angularjs-Rückrufe sind nicht synchron. (soweit ich weiß, das sind Situationen, in denen müssen Sie die Verwendung von $scope.$gelten, wenn Sie möchten, dass Ihre änderungen werden angewendet)
scope
innerhalb von eckigen oder von außen gewinkelt. So nach diesem wissen Sie immer, wenn Sie anrufen müssen scope.$apply
oder nicht. Und wenn Sie mit dem gleichen code für beide gewinkelt/nicht gewinkelt scope
manipulation, dann machst du es falsch, es sollte immer getrennt... also im Grunde, wenn Sie laufen in eine Falle, wo Sie brauchen, um zu überprüfen, scope.$$phase
, Ihr code ist nicht darauf ausgelegt, in der richtigen Weise, und es gibt immer einen Weg, es zu tun 'der richtige Weg' digest bereits in progress
- Fehler InformationsquelleAutor der Frage Dominik Goltermann | 2014-03-12
Du musst angemeldet sein, um einen Kommentar abzugeben.
Nach etwas mehr Graben, ich war in der Lage zu lösen, die Frage, ob es immer sicher zu bedienen
$scope.$apply
. Die kurze Antwort ist ja.Lange Antwort:
Durch, wie Ihr browser Javascript ausführt, ist es nicht möglich, dass zwei digest fordert, kollidieren durch Zufall.
Daher der Fehler "digest bereits in Bearbeitung" können nur auftreten, in einer situation: Wenn ein $gelten ausgegeben, die innerhalb einer anderen $gelten, z.B.:
Diese situation kann nicht entstehen wenn wir verwenden $Umfang.gelten in einer reinen nicht-angularjs Rückruf, wie zum Beispiel den Rückruf von
setTimeout
. Also der folgende code ist 100% kugelsicher und es ist keine müssenif (!$scope.$$phase) $scope.$apply()
selbst diese eine ist sicher:
Was ist NICHT sicher ist (weil $timeout - wie alle angularjs-Helfer - bereits Gespräche
$scope.$apply
für Sie):Dies erklärt auch, warum die Verwendung von
if (!$scope.$$phase) $scope.$apply()
ist ein anti-pattern. Sie wissen einfach nicht brauchen, wenn Sie$scope.$apply
in der richtigen Art und Weise: In einer reinen js-callback-wiesetTimeout
zum Beispiel.Lesen http://jimhoskins.com/2012/12/17/angularjs-and-apply.html für die ausführlichere Erklärung.
InformationsquelleAutor der Antwort Dominik Goltermann
Es ist definitiv ein anti-Muster jetzt. Ich habe gesehen, ein Schlag verdauen, auch wenn Sie das Kontrollkästchen für die $$ - phase. Du bist einfach nicht sollen Zugriff auf die interne API, gekennzeichnet durch
$$
Präfixe.Sollten Sie verwenden
als dies ist die bevorzugte Methode in den Winkel - ^1.4 und ist besonders exponiert, da ein API für den application layer.
InformationsquelleAutor der Antwort FlavorScape
In jedem Fall, wenn Ihr digest-in-progress und schieben Sie einen anderen Dienst, um zu verdauen, es gibt einfach eine Fehlermeldung, d.h. digest bereits im Gange ist.
also um dies zu heilen, haben Sie zwei Möglichkeiten.
Sie können überprüfen, ob es anyother digest in progress wie polling.
Erste
wenn die obige Bedingung erfüllt ist, dann gilt $scope.$gelten otherwies nicht und
zweite Lösung ist $timeout
wird es nicht zulassen, das andere verdauen zu starten, bis $timeout komplett ist, ist es die Ausführung.
InformationsquelleAutor der Antwort Lalit Sachdeva
scope.$apply
löst eine$digest
- Zyklus, die grundlegend ist für 2-Wege-DatenbindungEinen
$digest
Zyklus überprüft, für Objekte, D. H. Modelle(um genau zu sein$watch
), die an$scope
zu beurteilen, ob Ihre Werte geändert haben und, wenn er erkennt, ändern Sie dann die notwendigen Schritte, um die Ansicht zu aktualisieren.Nun, wenn Sie verwenden
$scope.$apply
Sie vor einem Fehler ", die Bereits im Gange" , so ist es ziemlich offensichtlich, dass $digest läuft, aber was es ausgelöst hat?ans--> alle
$http
fordert alle ng-klicken Sie auf wiederholen, wiederholen, zeigen, verstecken, etc auslösen$digest
Zyklus, UND DAS SCHLIMMSTE, ES LÄUFT JEDES $SCOPE.ie sagen, deine Seite hat 4 Controller oder Richtlinien A,B,C,D
Wenn du 4
$scope
Eigenschaften in jedem von Ihnen, dann haben Sie insgesamt 16 $scope Eigenschaften auf Ihrer Seite.Wenn Sie trigger
$scope.$apply
im controller D dann ein$digest
Zyklus wird überprüft, ob alle 16 Werte!!! plus alle $rootScope Eigenschaften.Antwort-->aber
$scope.$digest
löst eine$digest
auf Kind und der gleiche Umfang, so wird es prüfen, nur 4 Eigenschaften. Also, wenn Sie sicher sind, dass änderungen in D wird sich nicht auf A, B, C verwenden Sie dann$scope.$diges
t nicht$scope.$apply
.Also eine Reine ng-click oder ng-ein - /ausblenden möglicherweise das auslösen einer
$digest
Zyklus auf über 100+ Eigenschaften, auch wenn der Benutzer hat nicht gefeuert jedem Fall!InformationsquelleAutor der Antwort Rishul Matta
Verwenden
$timeout
es ist die Art, wie empfohlen.Mein Szenario ist, dass ich ändern müssen Elemente auf der Seite die auf der Grundlage der Daten erhielt ich von einem WebSocket. Und da es außerhalb von Winkel, ohne die $timeout, das einzige Modell wird zwar geändert, aber nicht die Sicht. Weil Eckig weiß nicht das Stück der Daten, die geändert wurde.
$timeout
ist im Grunde erzählen Winkel, um die änderung in die nächste Runde des $digest.Ich habe versucht, die folgenden auch, und es funktioniert. Der Unterschied für mich ist, dass die $timeout klarer ist.
InformationsquelleAutor der Antwort James J. Ye
Fand ich sehr Coole Lösung:
injizieren, wo Sie Sie brauchen:
InformationsquelleAutor der Antwort bora89