Ошибка: Достигнуто 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/

Ответ 8

Это случилось со мной сразу после обновления Firefox до версии 51. После clearing the cache проблема исчезла.

Ответ 9

i имела аналогичную ошибку, так как я определил

ng- class= "GetLink()"

вместо

нг кнопкой мыши = "GetLink()"