Помилка: досягнуто 10 ітерацій дайджесту (). Аборт! з динамічним предикатом сортування


134

У мене є такий код, який повторює і відображає ім’я користувача та його оцінка:

<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>

І відповідний кутовий контролер.

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 (). Аборт! помилка в моїй консолі.

Я створив jsfiddle для того ж.

Присудок сортування ініціалізується лише всередині ng-повтору, а також обмеження застосовується до кількості об'єктів. тож я відчуваю, що спостерігачі разом і sortby, і limitTo є причиною помилки.

Якщо $ range.reverse помилковий (порядок зростання балів), він не помиляється.

Хтось може допомогти мені зрозуміти, що тут не так? Багато вдячний за вашу допомогу.


Якщо ви видалите оператор if, чи все-таки помилка?
Матвій Берг

Дякуємо за вашу відповідь Метью! Я поставив діагноз помилково. Здається, проблема полягає у фільтрах сортування та limitTo. Я оновив питання з JSFiddle. Багато вдячний за вашу допомогу.
Chubby Boy

це кутова річ. Вам потрібно запам’ятати функції, а потім запам'ятати стан. Отримайте мою відповідь на stackoverflow.com/questions/14376879/…
Джуліо Марін

Відповіді:


116

Перевірте цей jsFiddle . (Код в основному той самий, який ви розмістили, але я використовую елемент замість вікна для прив'язки подій прокрутки).

Наскільки я бачу, немає жодної проблеми з опублікованим вами кодом. Помилка, яку ви згадали, зазвичай виникає під час створення циклу змін над властивістю. Наприклад, наприклад, коли ви спостерігаєте за змінами на певній властивості, а потім змінюєте значення цього властивості для слухача:

$scope.$watch('users', function(value) {
  $scope.users = [];
});

Це призведе до повідомлення про помилку:

Неприхована помилка: досягнуто 10 ітерацій дайджесту (). Аборт!
Спостерігачі звільнилися за останні 5 ітерацій: ...

Переконайтеся, що ваш код не має подібних ситуацій.

оновлення:

Це ваша проблема:

<div ng-init="user.score=user.id+1"> 

Не слід змінювати об'єкти / моделі під час візуалізації чи іншим способом, це призведе до примусового нового візуалізації (і, отже, циклу , що спричиняє ітерації 'Помилка: 10 $ дайджест (). Аборт!' ).

Якщо ви хочете оновити модель, робіть це на контролері чи на директиві, ніколи не переглядайте. angularjs документація рекомендує не використовуватиng-init точно , щоб уникнути таких ситуацій:

Використовуйте директиву ngInit у шаблонах (лише для іграшок / прикладних програм, не рекомендується для реальних програм)

Ось jsFiddle з робочим прикладом.


1
FYI, замість angular.element(w).bind()вас можна використовувати element.bind().
Марк Райкок

Дякую багато bmleite та Марку. Я поставив діагноз помилково. Будь ласка, дивіться мої коментарі вище. Я оновив питання з JSFiddle. Багато вдячний за вашу допомогу.
Chubby Boy

Дуже дякую @bmleite! Просто намагаюся зрозуміти більше. Але чому це так, якщо $ range.reverse = false (порядку зростання балу) не викликає помилок?
Chubby Boy

Для зростання та зменшення слід використовувати префікси "+" та "-" відповідно (тобто "+ оцінка" та "-скоре"). Більше інформації про це тут .
bmleite

1
Ця відповідь вирішила мою проблему. Пояснення добре тим, що воно описує проблему: помилка повторення $ digest () призводить до того, що ви намагаєтесь змінити властивість водночас, коли ви перебираєтеся. Таким чином, кожна зміна властивості ініціює оновлення перегляду (UI) і кутовий зрештою максимум на 10 циклів. Приклад jsFiddle поміняє зміну властивості в Controller. Зміна властивості у представленні призводить до цієї помилки.
mbokil

9

Причиною цієї помилки для мене стало ...

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);
}

Мені все ще цікаво, чому функція викликається не раз з ng-src? - тому що angular намагається створити html кілька разів, поки він не отримає 2 однакових результату. в цьому сенс досягнуто ітерацій 10 $ digest (), він спробував 10 разів і жодного разу не отримав 2 однакових результату
bresleveloper

@bresleveloper Ви могли б надати посилання з цією інформацією? Дякую.
Вілла

@Willa дивіться тут docs.angularjs.org/api/ng/type/$rootScope.Scope CTRF + F це "Межа повторної ітерації - 10, щоб запобігти безмежному глухому циклу"
bresleveloper

Дякую. Це допомогло.
Вілла

7

Для мене було те, що я передавав результат функції як двосторонній прив'язуючий вхід '=' до директиви, яка щоразу створювала новий об'єкт.

тож у мене було щось подібне:

<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

У мене є ще один приклад того, що це спричинило. Сподіваємось, це допомагає для подальшого використання. Я використовую 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);
});

Це звучить точно як проблема, яка у мене є. Проста функція, яка нічого не оновлювала, але створила локальний масив, повторила один існуючий масив $ range та створила об'єкти в локальному масиві та повернула. Зателефонувавши один раз і зберігаючи його в учаснику $ range, це вирішує проблему. Дякую. Хочете, я знав, у чому полягає проблема із використанням методу безпосередньо.
AgilePro

2

Досить пізно до партії, але у мене виникла проблема, тому що є дефект ui-роутера в кутовому 1.5.8 Варто зазначити, що ця помилка з’явилася лише в перший раз, коли я запустив програму, і вона не повториться після цього. Цей пост від Github вирішив мою проблему. В основному помилка передбачає, що $urlRouterProvider.otherwise("/home") рішення було таким способом:

$urlRouterProvider.otherwise(function($injector, $location) {
   var $state = $injector.get("$state");
   $state.go("your-state-for-home");
});

2

Для початку ігноруйте всі відповіді, скажіть вам використовувати $ watch. Кутовий вже працює від слухача. Я гарантую вам, що ви ускладнюєте речі, просто думаючи в цьому напрямку.

Ігноруйте всі відповіді, які підказують користувачеві $ 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-повтор за $ index, і коли довжина масиву дорівнює індексу, зупиніть цикл і виконайте свою логіку.

jsfiddle


1

Я отримав цю помилку в контексті управління кутовим деревом. У моєму випадку це були варіанти дерева. Я повертав treeOptions () з функції. Завжди повертався той самий об’єкт. Але Angular магічно вважає, що це новий об'єкт, а потім викликає дайджест циклу, щоб почати. Викликає рекурсію дайджестів. Рішення полягало в тому, щоб прив’язати версії дерева до обсягу. І призначте його лише один раз.


1

Це дивно ... У мене точно така ж помилка, що випливає з іншої речі. Коли я створюю свій контролер, я передав параметр $ location, наприклад:

App.controller('MessageController', function ($scope, $http, $log, $location, $attrs, MessageFactory, SocialMessageFactory) {
   // controller code
});

Це виявилося помилкою, коли ми використовуємо сторонні бібліотеки чи чистий JS для маніпулювання деякими особливостями (тут window.location), наступний дайджест кутових може призвести до помилки.

Тому я просто видалив $ location з параметра створення контролера, і він знову працював, без цієї помилки. Або якщо вам абсолютно потрібно використовувати розташування $ з кутового, вам потрібно видалити кожне <a href="#">link</a>з посилань сторінки вашої шаблону, а скоріше написати href = "" . Працювали для мене.

Сподіваюся, це може допомогти одного дня.



0

Це сталося зі мною відразу після оновлення Firefox до версії 51. Після clearing the cacheцього проблема пішла.



0

Це сталося зі мною після оновлення з кутового 1.6 -> 1.7 при використанні $ sce.trustAsResourceUrl () як повернене значення функції, викликаної з ng-src. Ви можете побачити цю проблему, згадану тут .

У моєму випадку мені довелося змінити наступне.

<source ng-src="{{trustSrc(someUrl)}}" type='video/mp4' />
trustSrc = function(url){
    return $sce.trustAsResourceUrl(url);
};

до

<source ng-src='{{trustedUrl}} type='video/mp4' />
trustedUrl = $sce.trustAsResourceUrl(someUrl);

0

Я отримав таку саму помилку, використовуючи AngularJS 1.3.9, коли я у своєму спеціальному фільтрі сортування викликав Array.reverse ()

Після того, як я її зняв, це стало добре.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.