2016-05-25 6 views
3

Betrachten Sie die folgende plunker

Hier ist die html

<div ng-repeat="(id, testOject) in filterList()"> 
     <div ng-if="testOject['state']"> 
     {{testObject}} 
     </div> 
    </div> 

ist hier der relevante js

$scope.test = { 
    '1': {'state': true, 'label': '1'} 
    } 

    $scope.filterList = function() { 
    var map = {}; 

    for (var key in $scope.test){ 
     if($scope.test[key]['state']) { 
     map[key] = { 
      'state': $scope.test[key]['state'], 
      'label': $scope.test[key]['label'] 
     } 
     } 
    } 
    return map; 
    }; 

Der obige Code verursacht 10 $digest() iterations reached Fehler.

Allerdings, wenn wir die code ein bisschen ändern.

$scope.filterList = function() { 
    var map = {}; 

    for (var key in $scope.test){ 
     if($scope.test[key]['state']) { 
     map[key] = true 
     } 
    } 
    return map; 
    }; 

Der Fehler nicht

Es scheint, wie Änderung tritt Erkennung ausgelöst wird, wenn ein neues key, die ein ganz neues Objekt enthalten wird aktualisiert, aber ich habe nur ein Objekt im Wörterbuch, warum tut es durchschleifen Änderung Erkennung 10 mal?

+0

Digest wird ausgeführt, während sich der Bereich ändert. Der Filter sollte dieselben Objekte/Arrays zurückgeben, wenn die Daten bereits gefiltert, nicht neu erstellt wurden. –

Antwort

2

From error page:

Dieser Fehler tritt auf, wenn das Modell und die anschließende $digest Zyklus eine Zustandsänderung instabil und löst jeder $digest Zyklus wird der Anwendung. Angular erkennt diese Situation und verhindert, dass eine Endlosschleife dazu führt, dass der Browser nicht mehr reagiert.

Zum Beispiel kann die Situation auftreten, indem Sie eine Uhr auf einem Pfad einrichten und anschließend den gleichen Pfad aktualisieren, wenn sich der Wert ändert.

$scope.$watch('foo', function() { 
     $scope.foo = $scope.foo + 1; 
    }); 

Ein häufiger Fehler an eine Funktion ist, die Bindung, die aufgerufen wird es jedesmal, wenn eine neue Array erzeugt. Zum Beispiel:

<div ng-repeat="user in getUsers()">{{ user.name }}</div> 

... 

$scope.getUsers = function() { 
    return [ { name: 'Hank' }, { name: 'Francisco' } ]; 
}; 

Da getUsers() gibt ein neues Array bestimmt, dass das Angular Modell auf jeden $digest Zyklus unterschiedlich ist, in dem Fehler zur Folge hat. Die Lösung ist das gleiche Array-Objekt zurückzugeben, wenn die Elemente nicht geändert:

var users = [ { name: 'Hank' }, { name: 'Francisco' } ]; 

$scope.getUsers = function() { 
    return users; 
}; 

Die maximale Anzahl erlaubter Wiederholungen des Zyklus $ verdaulich ist über TTL-Einstellung gesteuert, die so konfiguriert werden können, über $rootScopeProvider.

Für Ihren Fall können Sie folgenden Code verwenden:

Working Demo

var map = {}; 
    $scope.createArray = function() {  

    for (var key in $scope.test){ 
     if($scope.test[key]['state']) { 
     map[key] = { 
      'state': $scope.test[key]['state'], 
      'label': $scope.test[key]['label'] 
     } 
     } 
    } 
    return map; 
    }; 

    $scope.filterList = function() { 
     return map; 
    } 
1

Vom docs

The $digest loop keeps iterating until the model stabilizes 

dh den Digest stoppt, wenn Ihr Modell nicht mehr wechselt zwischen 2 aufeinanderfolgenden Zyklen.

Der Code:

map[key] = { 
     'state': $scope.test[key]['state'], 
     'label': $scope.test[key]['label'] 
    } 

ordnet ein neues Objekt zu map[key] bei jedem Zyklus verdauen, so das Modell nie stabilisiert.

der Code:

map[key] = true 

ordnet eine Boolesche Primitiv zu map[key], die nicht zwischen 2 aufeinander folgenden Zyklen verdauen ändert so das Modell stabil wird.

Um Ihre Karte zu stabilisieren, können Sie eine Bereichsvariable erstellen und nur die Attribute des Objekts map[key] ändern. Siehe plunker

$scope.map = {}; 

    $scope.filterList = function() { 
    for (var key in $scope.test){ 
     if($scope.test[key]['state']) { 
     $scope.map[key] = $scope.map[key] || {}; 
     $scope.map[key].state = $scope.test[key]['state']; 
     $scope.map[key].label = $scope.test[key]['label']; 
     } 
    } 

    return $scope.map; 
    }; 
+0

Aber es ändert sich nur einmal, da mein Wörterbuch die Größe 1 ist, also sollte es innerhalb von 10 Zyklen Grenze sein? – testing

+1

@testing Ich beziehe mich nicht auf 'for (var Schlüssel in $ scope.test)'. Ich beziehe mich auf den Digest-Zyklus. So wird Zyklus 1, filterList() aufgerufen und '$ scope.map ['1'] = newObject'. Zyklus 2, filterList() wird aufgerufen und '$ scope.map ['1'] = anotherNewObject'. Also ist '$ scope.map ['1']' ein anderes Objekt zwischen den Digest-Zyklen 1 und 2 und so beginnt Zyklus 3. Zyklus 3 unterscheidet sich von Zyklus 2 und Zyklus 4 beginnt und so weiter ... – user2718281

Verwandte Themen