Errore: raggiunte 10 $ iterazioni digest (). Interruzione! con predicato di ordinamento dinamico


134

Ho il seguente codice che ripete e visualizza il nome dell'utente e il suo punteggio:

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

E il corrispondente controller angolare.

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'}]
}

Quando eseguo il codice sopra, ottengo l' errore: 10 $ digest () iterazioni raggiunte. Interruzione! errore nella mia console.

Ho creato jsfiddle per lo stesso.

Il predicato di ordinamento viene inizializzato solo all'interno di ng-repeat e anche il limite viene applicato al numero di oggetti. quindi sento che avere sia l'ordinamento che il limite Per guardare insieme è la ragione dell'errore.

Se $ scope.reverse è falso (ordine di punteggio crescente), allora non si verifica un errore.

Qualcuno può aiutarmi a capire cosa c'è che non va qui? Apprezzo molto il tuo aiuto.


Se rimuovi l'istruzione if, si verifica ancora un errore?
Mathew Berg,

Grazie per la tua risposta Mathew! Ho diagnosticato il problema in modo errato. Il problema sembra riguardare i filtri sortby e limitTo. Ho aggiornato la domanda con JSFiddle. Apprezzo molto il tuo aiuto.
Chubby Boy,

questa è una cosa angolare. Devi memorizzare le tue funzioni e poi ricordare lo stato. Prendi la mia risposta su stackoverflow.com/questions/14376879/…
Julio Marins,

Risposte:


116

Si prega di controllare questo jsFiddle . (Il codice è sostanzialmente lo stesso che hai pubblicato ma io uso un elemento al posto della finestra per associare gli eventi di scorrimento).

Per quanto posso vedere, non c'è nessun problema con il codice che hai pubblicato. L'errore che hai citato di solito si verifica quando si crea un ciclo di modifiche su una proprietà. Ad esempio, come quando si osservano le modifiche su una determinata proprietà e quindi si modifica il valore di quella proprietà sul listener:

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

Ciò comporterà un messaggio di errore:

Errore non rilevato: sono state raggiunte 10 iterazioni digest (). Interruzione!
Gli osservatori hanno sparato nelle ultime 5 iterazioni: ...

Assicurati che il tuo codice non abbia questo tipo di situazioni.

aggiornare:

Questo è il tuo problema:

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

Non dovresti cambiare oggetti / modelli durante il rendering o altrimenti, forzerà un nuovo rendering (e di conseguenza un ciclo , che causa l '"Errore: 10 $ digest () iterazioni raggiunte. Interruzione!" ).

Se vuoi aggiornare il modello, fallo sul Controller o su una Direttiva, mai sulla vista. documentazione angularjs raccomanda di non utilizzare il ng-initproprio per evitare questo tipo di situazioni:

Usa la direttiva ngInit nei modelli (solo per app giocattolo / esempio, non raccomandato per applicazioni reali)

Ecco un jsFiddle con un esempio funzionante.


1
Cordiali saluti, invece di angular.element(w).bind()te puoi usare element.bind().
Mark Rajcok,

Grazie mille bmleite e Mark. Ho diagnosticato il problema in modo errato. Si prega di vedere i miei commenti sopra. Ho aggiornato la domanda con JSFiddle. Apprezzo molto il tuo aiuto.
Chubby Boy,

Grazie mille @bmleite! Sto solo cercando di capire di più. Ma perché se $ scope.reverse = false (ordine di punteggio crescente) non causa errori?
Chubby Boy,

Per salire e scendere, utilizzare i prefissi '+' e '-', rispettivamente (ovvero '+ punteggio' e '-score'). Maggiori informazioni su questo qui .
bmleite,

1
Questa risposta ha risolto il mio problema. La spiegazione è buona in quanto descrive il problema: l'errore iterazioni $ digest () si verifica quando si tenta di modificare una proprietà mentre si esegue il ciclo. Pertanto, ogni modifica della proprietà attiva un aggiornamento della vista (UI) e l'angolazione alla fine raggiunge il massimo a 10 loop. L'esempio jsFiddle inserisce la modifica della proprietà nel controller. La modifica della proprietà in Visualizza comporta questo errore.
mbokil,

9

La causa di questo errore per me è stata ...

ng-if="{{myTrustSrc(chat.src)}}"

nel mio modello

Fa sì che la funzione myTrustSrc nel mio controller venga chiamata in un ciclo infinito. Se rimuovo ng-if da questa riga, il problema è risolto.

<iframe ng-if="chat.src" id='chat' name='chat' class='chat' ng-src="{{myTrustSrc(chat.src)}}"></iframe>

La funzione viene chiamata solo poche volte quando non viene utilizzato ng-if. Mi chiedo ancora perché la funzione venga chiamata più di una volta con ng-src?

Questa è la funzione nel controller

$scope.myTrustSrc = function(src) {
    return $sce.trustAsResourceUrl(src);
}

Mi chiedo ancora perché la funzione venga chiamata più di una volta con ng-src? - perché angolare tenta di creare l'html alcune volte fino a ottenere 2 risultati identici. questo è il significato dell'errore 10 $ digest () iterazioni raggiunte, ha provato 10 volte e non ha mai ottenuto 2 risultati identici
bresleveloper

@bresleveloper potresti fornire un link con queste informazioni? Grazie.
Willa,

@Willa guarda qui docs.angularjs.org/api/ng/type/$rootScope.Scope CTRF + F questo "Il limite di ripetizione dell'iterazione è 10 per prevenire un deadlock loop infinito"
bresleveloper

Grazie. Questo ha aiutato.
Willa,

7

Per me è stato che stavo passando un risultato di funzione come input di legame bidirezionale '=' a una direttiva che creava un nuovo oggetto ogni volta.

quindi ho avuto qualcosa del genere:

<my-dir>
   <div ng-repeat="entity in entities">
      <some-other-dir entity="myDirCtrl.convertToSomeOtherObject(entity)"></some-other-dir>
   </div>
</my-dir>

e il metodo controller su my-dir era

this.convertToSomeOtherObject(entity) {
   var obj = new Object();
   obj.id = entity.Id;
   obj.value = entity.Value;
   [..]
   return obj;
}

che quando ho fatto

this.convertToSomeOtherObject(entity) {
   var converted = entity;
   converted.id = entity.Id;
   converted.value = entity.Value;
   [...]
   return converted;
}

problema risolto!

Spero che questo possa aiutare qualcuno :)


5

Ho un altro esempio di qualcosa che ha causato questo. Speriamo che aiuti per riferimento futuro. Sto usando AngularJS 1.4.1.

Ho avuto questo markup con più chiamate a una direttiva personalizzata:

<div ng-controller="SomeController">
    <myDirective data="myData.Where('IsOpen',true)"></myDirective>
    <myDirective data="myData.Where('IsOpen',false)"></myDirective>
</div>

myDataè un array ed Where()è un metodo di estensione che scorre sull'array restituendo un nuovo array contenente tutti gli elementi dall'originale in cui la proprietà IsOpen corrisponde al valore bool nel secondo parametro.

Nel controller ho impostato in $scope.dataquesto modo:

DataService.getData().then(function(results){
    $scope.data = results;
});

Il Where()problema era chiamare il metodo di estensione dalla direttiva come nel markup sopra. Per risolvere questo problema ho spostato la chiamata al metodo di estensione nel controller anziché nel markup:

<div ng-controller="SomeController">
    <myDirective data="openData"></myDirective>
    <myDirective data="closedData"></myDirective>
</div>

e il nuovo codice controller:

DataService.getData().then(function(results){
    $scope.openData = results.Where('IsOpen',true);
    $scope.closedData = results.Where('IsOpen',false);
});

Sembra esattamente il problema che ho. Una semplice funzione che non aggiornava nulla, ma creava un array locale, ripeteva su un array $ scope esistente, creava oggetti nell'array locale e restituiva. Chiamando una volta e memorizzandolo in un membro $ scope risolve il problema. Grazie. Vorrei sapere qual è il problema con l'utilizzo diretto del metodo.
AgilePro,

2

Abbastanza tardi alla festa, ma il mio problema si stava verificando perché c'è un difetto nell'UI-router nell'angolo 1.5.8. Una cosa da menzionare è che questo errore è apparso solo la prima volta che stavo eseguendo l'applicazione e non si sarebbe ripresentato in seguito. Questo post di Github ha risolto il mio problema. Fondamentalmente l'errore comporta $urlRouterProvider.otherwise("/home") La soluzione è stata una soluzione alternativa come questa:

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

2

Per cominciare ignora tutte le risposte con ti dice di usare $ watch. Angular funziona già da un ascoltatore. Ti garantisco che stai complicando le cose semplicemente pensando in questa direzione.

Ignora tutte le risposte che ti dicono all'utente $ timeout. Non puoi sapere quanto tempo impiegherà la pagina a caricarsi, quindi questa non è la soluzione migliore.

Devi solo sapere quando il rendering della pagina è terminato.

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

Tieni traccia di ng-repeat di $ index e quando la lunghezza dell'array è uguale all'indice, interrompi il ciclo e esegui la tua logica.

jsfiddle


1

Ho riscontrato questo errore nel contesto del controllo ad albero angolare. Nel mio caso sono state le opzioni dell'albero. Stavo restituendo treeOptions () da una funzione. Restituiva sempre lo stesso oggetto. Ma Angular pensa magicamente che si tratta di un nuovo oggetto e quindi fa iniziare un ciclo digest. Causando una ricorsione di digestioni. La soluzione consisteva nel legare treeOptions all'ambito. E assegnalo solo una volta.


1

È strano ... Ho lo stesso errore esatto, proveniente da una cosa diversa. Quando creo il mio controller ho passato il parametro $ location, in questo modo:

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

Questo si è rivelato un bug quando usiamo librerie di terze parti o JS puro per manipolare alcuni dettagli (qui window.location) il prossimo digest di angular farà esplodere questo errore.

Quindi ho semplicemente rimosso la posizione $ dal parametro di creazione del controller e ha funzionato di nuovo, senza questo errore. Oppure, se hai assolutamente bisogno di usare $ location da angolare, devi rimuovere tutti <a href="#">link</a>i link nei tuoi template page e scrivere href = "" . Ha funzionato per me.

Spero che possa essere d'aiuto un giorno.



0

Questo mi è successo subito dopo aver aggiornato Firefox alla versione 51. Dopo clearing the cache, il problema è andato.



0

Questo mi è successo dopo l'aggiornamento da 1.6 -> 1.7 angolare quando si utilizza $ sce.trustAsResourceUrl () come valore di ritorno di una funzione chiamata da ng-src. Puoi vedere questo problema menzionato qui .

Nel mio caso ho dovuto modificare quanto segue.

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

per

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

0

Ho ottenuto lo stesso errore esatto usando AngularJS 1.3.9 quando, nel mio filtro di ordinamento personalizzato, ho invocato Array.reverse ()

Dopo averlo rimosso, sarebbe andato tutto bene.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.