Ошибка: Достигнуто 10 $digest() итераций. Aborting! с динамическим сортировочным предикатом
У меня есть следующий код, который повторяет и отображает имя пользователя и его счет:
<div ng-controller="AngularCtrl" ng-app>
<div ng-repeat="user in users | orderBy:predicate:reverse | limitTo:10">
<div ng-init="user.score=user.id+1">
{{user.name}} and {{user.score}}
</div>
</div>
</div>
И соответствующий контроллер angular.
function AngularCtrl($scope) {
$scope.predicate = 'score';
$scope.reverse = true;
$scope.users = [{id: 1, name: 'John'}, {id: 2, name: 'Ken'}, {id: 3, name: 'smith'}, {id: 4, name: 'kevin'}, {id: 5, name: 'bob'}, {id: 6, name: 'Dev'}, {id: 7, name: 'Joe'}, {id: 8, name: 'kevin'}, {id: 9, name: 'John'}, {id: 10, name: 'Ken'}, {id: 11, name: 'John'}, {id: 1, name: 'John'}, {id: 2, name: 'Ken'}, {id: 3, name: 'smith'}, {id: 4, name: 'kevin'}, {id: 5, name: 'bob'}, {id: 6, name: 'Dev'}, {id: 7, name: 'Joe'}, {id: 8, name: 'kevin'}, {id: 9, name: 'John'}, {id: 10, name: 'Ken'}]
}
Когда я запускаю вышеуказанный код, я получаю завершенные итерации Ошибка: 10 $digest(). Aborting! в моей консоли.
Я создал jsfiddle для этого.
http://jsfiddle.net/JSWorld/7ecYd/1/
Предикат сортировки инициализируется только внутри ng-repeat, а также предел применяется к числу объектов. поэтому я чувствую, что причиной появления ошибки являются как сортировка, так и ограничение для наблюдателей.
Если значение $scope.reverse равно false (возрастающий порядок оценки), то это не ошибка.
Может кто-нибудь помочь мне понять, что здесь не так? Очень ценю вашу помощь.
Ответы
Ответ 1
Пожалуйста, проверьте этот jsFiddle: http://jsfiddle.net/bmleite/Hp4W7/. (Код в основном тот же, что и вы, но я использую элемент вместо окна для привязки событий прокрутки).
Насколько я вижу, нет проблем с кодом, который вы опубликовали. Указанная вами ошибка обычно возникает, когда вы создаете цикл изменений над свойством. Например, например, когда вы наблюдаете за изменениями определенного свойства и затем изменяете значение этого свойства в слушателе:
$scope.$watch('users', function(value) {
$scope.users = [];
});
Это приведет к сообщению об ошибке:
Неисправность Ошибка: Достигнуто 10 $digest() итераций. Aborting!
Зрителей выстрелил в последние 5 итераций:...
Убедитесь, что ваш код не имеет таких ситуаций.
обновление:
Это ваша проблема:
<div ng-init="user.score=user.id+1">
Вы не должны изменять объекты/модели во время рендеринга или иначе это будет вынуждать новый рендер (и, следовательно, цикл, который приведет к завершению итераций "Ошибка: 10 $digest(). Aborting!" ).
Если вы хотите обновить модель, сделайте это на контроллере или на директиве, но никогда не увидите. Документация angularjs рекомендует не использовать ng-init
, чтобы избежать таких ситуаций:
Использовать директиву ngInit в шаблонах (только для игрушечных/примерных приложений, а не рекомендуется для реальных приложений)
Здесь jsFiddle с рабочим примером: http://jsfiddle.net/bmleite/7ecYd/3/
Ответ 2
Причиной этой ошибки для меня было...
ng-if="{{myTrustSrc(chat.src)}}"
в моем шаблоне
Это вызывает вызов функции myTrustSrc в моем контроллере в бесконечном цикле. Если я удалю ng-if из этой строки, проблема будет решена.
<iframe ng-if="chat.src" id='chat' name='chat' class='chat' ng-src="{{myTrustSrc(chat.src)}}"></iframe>
Функция вызывается только несколько раз, когда ng-if не используется. Я все еще удивляюсь, почему функция вызывается более одного раза с помощью ng-src?
Это функция в контроллере
$scope.myTrustSrc = function(src) {
return $sce.trustAsResourceUrl(src);
}
Ответ 3
У меня есть еще один пример того, что вызвало это. Надеюсь, это поможет в будущем. Я использую AngularJS 1.4.1.
У меня была эта разметка с несколькими вызовами пользовательской директивы:
<div ng-controller="SomeController">
<myDirective data="myData.Where('IsOpen',true)"></myDirective>
<myDirective data="myData.Where('IsOpen',false)"></myDirective>
</div>
myData
- это массив, а Where()
- это метод расширения, который выполняет итерацию по массиву, возвращая новый массив, содержащий любые элементы из оригинала, где свойство IsOpen соответствует значению bool во втором параметре.
В контроллере я установил $scope.data
следующим образом:
DataService.getData().then(function(results){
$scope.data = results;
});
Вызов метода расширения Where()
из директивы, как в приведенной выше разметке, был проблемой. Чтобы устранить эту проблему, я переместил вызов метода расширения в контроллер вместо разметки:
<div ng-controller="SomeController">
<myDirective data="openData"></myDirective>
<myDirective data="closedData"></myDirective>
</div>
и новый код контроллера:
DataService.getData().then(function(results){
$scope.openData = results.Where('IsOpen',true);
$scope.closedData = results.Where('IsOpen',false);
});
Ответ 4
Для меня было то, что я передавал результат функции как двухсторонний ввод привязки '=' в директиву, которая каждый раз создавала новый объект.
поэтому у меня было что-то вроде этого:
<my-dir>
<div ng-repeat="entity in entities">
<some-other-dir entity="myDirCtrl.convertToSomeOtherObject(entity)"></some-other-dir>
</div>
</my-dir>
и метод контроллера в my-dir был
this.convertToSomeOtherObject(entity) {
var obj = new Object();
obj.id = entity.Id;
obj.value = entity.Value;
[..]
return obj;
}
который, когда я сделал для
this.convertToSomeOtherObject(entity) {
var converted = entity;
converted.id = entity.Id;
converted.value = entity.Value;
[...]
return converted;
}
решил проблему!
Надеюсь, это поможет кому-то:)
Ответ 5
Это странно... У меня точно такая же ошибка, исходящая из другой вещи. Когда я создаю свой контроллер, я передал параметр $location, например:
App.controller('MessageController', function ($scope, $http, $log, $location, $attrs, MessageFactory, SocialMessageFactory) {
// controller code
});
Это оказалось ошибкой https://github.com/angular/angular.js/issues/1417
когда мы используем сторонние библиотеки или чистую JS для управления некоторыми особенностями (здесь window.location), следующий дайджест angular ударит эту ошибку.
Поэтому я просто удалил $location из параметра создания контроллера, и он снова работал без этой ошибки.
Или, если вам абсолютно необходимо использовать $location из angular, вам нужно удалить все <a href="#">link</a>
в ссылках вашей страницы шаблона и скорее написать href="". Работал для меня.
Надеюсь, однажды это поможет.
Ответ 6
Для начала проигнорируйте все ответы, указав, что вы используете $watch. Angular работает уже прослушиватель. Я гарантирую вам, что вы усложняете вещи, просто думая в этом направлении.
Игнорировать все ответы, которые сообщают пользователю $timeout. Вы не можете знать, сколько времени займет страница для загрузки, поэтому это не лучшее решение.
Вам нужно только знать, когда страница будет выполнена.
<div ng-app='myApp'>
<div ng-controller="testctrl">
<label>{{total}}</label>
<table>
<tr ng-repeat="item in items track by $index;" ng-init="end($index);">
<td>{{item.number}}</td>
</tr>
</table>
</div>
var app = angular.module('myApp', ["testctrl"]);
var controllers = angular.module("testctrl", []);
controllers.controller("testctrl", function($scope) {
$scope.items = [{"number":"one"},{"number":"two"},{"number":"three"}];
$scope.end = function(index){
if(index == $scope.items.length -1
&& typeof $scope.endThis == 'undefined'){
/// DO STUFF HERE
$scope.total = index + 1;
$scop.endThis = true;
}
}
});
Отслеживать ng-repeat по индексу $index, и когда длина массива равна индексу, остановите цикл и выполните свою логику.
https://jsfiddle.net/jlynch83/hb1dg7jf/16/
Ответ 7
Если вы используете angular, удалите профиль ng-storage из консоли вашего браузера.
Это не общий бит решения. Он работал в моем случае.
В Chrome F12- > Ресурсы- > Локальное хранилище
Ответ 8
Это случилось со мной сразу после обновления Firefox до версии 51. После clearing the cache
проблема исчезла.
Ответ 9
i имела аналогичную ошибку, так как я определил
ng- class= "GetLink()"
вместо
нг кнопкой мыши = "GetLink()"