Kesalahan: 10 $ digest () iterasi tercapai. Membatalkan! dengan predikat sortir dinamis

135

Saya memiliki kode berikut yang berulang dan menampilkan nama pengguna dan skornya:

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

Dan pengontrol sudut yang sesuai.

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

Ketika saya menjalankan kode di atas, saya mendapatkan kesalahan: 10 $ digest () iterasi tercapai. Membatalkan! kesalahan di konsol saya.

Saya telah membuat jsfiddle untuk hal yang sama.

Predikat pengurutan diinisialisasi hanya di dalam ng-repeat dan juga batas diterapkan pada jumlah objek. jadi saya merasa memiliki sortby dan limitTo pengamat bersama-sama adalah alasan kesalahan.

Jika $ scope.reverse salah (urutan skor menaik), maka itu tidak salah.

Adakah yang bisa membantu saya memahami apa yang salah di sini? Terima kasih atas bantuan Anda.

Anak laki-laki gemuk
sumber
Jika Anda menghapus pernyataan if, apakah masih error?
Mathew Berg
Terima kasih atas tanggapan Anda, Mathew! Saya salah mendiagnosis masalah. Masalahnya tampaknya ada pada filter sortby dan limitTo. Saya telah memperbarui pertanyaan dengan JSFiddle. Terima kasih atas bantuan Anda.
Chubby Boy
ini adalah hal yang bersudut. Anda perlu membuat memo fungsi Anda dan kemudian mengingat negara. Dapatkan jawaban saya di stackoverflow.com/questions/14376879/…
Julio Marins

Jawaban:

116

Silakan periksa jsFiddle ini . (Kode pada dasarnya sama dengan yang Anda posting tetapi saya menggunakan elemen, bukan jendela untuk mengikat acara gulir).

Sejauh yang saya bisa lihat, tidak ada masalah dengan kode yang Anda posting. Kesalahan yang Anda sebutkan biasanya terjadi saat Anda membuat putaran perubahan pada properti. Misalnya, seperti saat Anda mengamati perubahan pada properti tertentu dan kemudian mengubah nilai properti tersebut pada pendengar:

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

Ini akan menghasilkan pesan kesalahan:

Kesalahan Tidak Tertangkap: 10 $ digest () iterasi tercapai. Membatalkan!
Pengamat menembak dalam 5 iterasi terakhir: ...

Pastikan kode Anda tidak memiliki situasi seperti ini.

memperbarui:

Ini masalahmu:

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

Anda tidak boleh mengubah objek / model selama rendering atau sebaliknya, ini akan memaksa render baru (dan akibatnya loop , yang menyebabkan iterasi 'Error: 10 $ digest () tercapai. Aborting!' ).

Jika Anda ingin memperbarui model, lakukan pada Controller atau pada Directive, jangan pada tampilan. dokumentasi angularjs merekomendasikan untuk tidak menggunakan yang ng-inittepat untuk menghindari situasi semacam ini:

Gunakan direktif ngInit di template (hanya untuk aplikasi mainan / contoh, tidak disarankan untuk aplikasi nyata)

Berikut adalah jsFiddle dengan contoh yang berfungsi.

bmleite
sumber
1
FYI, alih-alih angular.element(w).bind()Anda bisa menggunakan element.bind().
Mark Rajcok
Terima kasih banyak bmleite dan Mark. Saya salah mendiagnosis masalah. Silakan lihat komentar saya di atas. Saya telah memperbarui pertanyaan dengan JSFiddle. Terima kasih atas bantuan Anda.
Chubby Boy
Terima kasih banyak @bmleite! Hanya mencoba untuk lebih memahami. Tapi mengapa jika $ scope.reverse = false (ascending order of score) tidak menyebabkan kesalahan?
Chubby Boy
Untuk naik dan turun Anda harus menggunakan awalan '+' dan '-', masing-masing (yaitu '+ skor' dan '-score'). Informasi lebih lanjut tentang ini di sini .
bmleite
1
Jawaban ini memecahkan masalah saya. Penjelasannya bagus karena menjelaskan masalah: kesalahan iterasi $ digest () terjadi saat Anda mencoba memodifikasi properti pada saat yang sama Anda mengulanginya. Jadi, setiap perubahan properti memicu pembaruan tampilan (UI) dan sudut akhirnya maksimal 10 kali pengulangan. Contoh jsFiddle menempatkan perubahan properti di Controller. Mengubah properti di View menghasilkan kesalahan ini.
mbokil
9

Penyebab kesalahan ini bagi saya adalah ...

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

di template saya

Ini menyebabkan fungsi myTrustSrc di pengontrol saya dipanggil dalam loop tanpa akhir. Jika saya menghapus ng-if dari baris ini, maka masalahnya sudah terpecahkan.

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

Fungsi ini hanya dipanggil beberapa kali saat ng-if tidak digunakan. Saya masih bertanya-tanya mengapa fungsinya dipanggil lebih dari sekali dengan ng-src?

Ini adalah fungsi di pengontrol

$scope.myTrustSrc = function(src) {
    return $sce.trustAsResourceUrl(src);
}
Natus Drew
sumber
Saya masih bertanya-tanya mengapa fungsinya dipanggil lebih dari sekali dengan ng-src? - karena angular mencoba membuat html beberapa kali hingga mendapatkan 2 hasil yang identik. itulah arti dari kesalahan 10 $ digest () iterasi yang dicapai, dia mencoba 10 kali dan tidak pernah mendapatkan 2 hasil yang identik
bresleveloper
@bresleveloper dapatkah Anda memberikan tautan dengan informasi ini? Terima kasih.
Willa
@Willa lihat di sini docs.angularjs.org/api/ng/type/$rootScope.Scope CTRF + F ini "Batas iterasi ulang adalah 10 untuk mencegah kebuntuan loop tak terbatas"
bresleveloper
Terima kasih. Itu membantu.
Willa
7

Bagi saya itu adalah bahwa saya meneruskan hasil fungsi sebagai input pengikat 2 arah '=' ke direktif yang membuat objek baru setiap saat.

jadi saya punya sesuatu seperti itu:

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

dan metode pengontrol pada my-dir adalah

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

yang ketika saya buat

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

memecahkan masalah!

Semoga ini akan membantu seseorang :)

Michail Michailidis
sumber
5

Saya punya contoh lain dari sesuatu yang menyebabkan ini. Semoga membantu untuk referensi kedepannya. Saya menggunakan AngularJS 1.4.1.

Saya memiliki markup ini dengan beberapa panggilan ke perintah kustom:

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

myDataadalah sebuah larik dan Where()merupakan metode ekstensi yang mengulangi larik yang mengembalikan larik baru yang berisi item apa pun dari aslinya di mana properti IsOpen cocok dengan nilai bool di parameter kedua.

Di pengontrol saya atur $scope.dataseperti ini:

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

Memanggil Where()metode ekstensi dari arahan seperti pada markup di atas adalah masalahnya. Untuk memperbaiki masalah ini, saya memindahkan panggilan ke metode ekstensi ke pengontrol alih-alih markup:

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

dan kode pengontrol baru:

DataService.getData().then(function(results){
    $scope.openData = results.Where('IsOpen',true);
    $scope.closedData = results.Where('IsOpen',false);
});
squillman
sumber
Kedengarannya persis seperti masalah yang saya miliki. Fungsi sederhana yang tidak mengupdate apa pun, tetapi membuat array lokal, melakukan iterasi pada satu array $ scope yang ada, dan membuat objek dalam array lokal, dan dikembalikan. Dengan memanggil sekali dan menyimpannya dalam anggota $ scope itu memecahkan masalah. Terima kasih. Seandainya saya tahu apa masalah menggunakan metode ini secara langsung.
AgilePro
2

Cukup terlambat ke pesta tetapi masalah saya terjadi karena ada cacat pada ui-router di sudut 1.5.8. Satu hal yang perlu disebutkan adalah bahwa kesalahan ini hanya muncul pertama kali saya menjalankan aplikasi dan tidak akan terulang kembali setelahnya. Posting dari github ini menyelesaikan masalah saya. Pada dasarnya kesalahan melibatkan $urlRouterProvider.otherwise("/home") Solusinya adalah solusi seperti ini:

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

Sebagai permulaan abaikan semua jawaban dengan menyuruh Anda menggunakan $ watch. Angular sudah berfungsi dari pendengar. Saya jamin bahwa Anda memperumit banyak hal hanya dengan berpikir ke arah ini.

Abaikan semua jawaban yang memberi tahu Anda untuk pengguna $ timeout. Anda tidak dapat mengetahui berapa lama waktu yang dibutuhkan untuk memuat halaman, oleh karena itu ini bukan solusi terbaik.

Anda hanya perlu mengetahui saat halaman selesai dirender.

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

Lacak ng-repeat dengan $ index dan ketika panjang array sama dengan indeks, hentikan loop dan lakukan logika Anda.

jsfiddle.dll

Jed Lynch
sumber
1

Saya mendapat kesalahan ini dalam konteks kontrol pohon sudut. Dalam kasus saya, itu adalah opsi pohon. Saya mengembalikan treeOptions () dari sebuah fungsi. Itu selalu mengembalikan objek yang sama. Tapi Angular secara ajaib berpikir bahwa itu adalah objek baru dan kemudian menyebabkan siklus intisari dimulai. Menyebabkan rekursi pencernaan. Solusinya adalah mengikat treeOptions ke cakupan. Dan tetapkan sekali saja.

JDev
sumber
1

Aneh ... Saya mendapat kesalahan yang sama persis, berasal dari hal yang berbeda. Ketika saya membuat pengontrol saya, saya meneruskan parameter $ location, seperti ini:

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

Ini terbukti sebagai bug ketika kami menggunakan pustaka pihak ketiga atau JS murni untuk memanipulasi beberapa hal spesifik (di sini window.location) intisari sudut berikutnya akan meniup kesalahan ini.

Jadi saya hanya menghapus $ location dari parameter pembuatan pengontrol, dan itu berfungsi lagi, tanpa kesalahan ini. Atau jika Anda benar-benar perlu menggunakan $ location dari sudut, Anda harus menghapus semua <a href="#">link</a>link di halaman template Anda, dan lebih baik menulis href = "" . Bekerja untuk saya.

Semoga bisa membantu suatu hari nanti.

Alex
sumber
0

Ini terjadi pada saya tepat setelah mengupgrade Firefox ke versi 51. Setelah itu clearing the cache, masalah telah hilang.

Zsolti
sumber
0

saya mengalami kesalahan serupa, karena saya telah menentukan

ng-class = "GetLink ()"

dari pada

ng-click = "GetLink ()"

Satish Kumar sonker
sumber
0

Hal ini terjadi pada saya setelah memutakhirkan dari angular 1.6 -> 1.7 saat menggunakan $ sce.trustAsResourceUrl () sebagai nilai kembalian dari fungsi yang dipanggil dari ng-src. Anda dapat melihat masalah ini disebutkan di sini .

Dalam kasus saya, saya harus mengubah yang berikut ini.

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

untuk

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

Saya mendapat kesalahan yang sama persis menggunakan AngularJS 1.3.9 ketika saya, dalam filter-sortir kustom saya, memanggil Array.reverse ()

Setelah saya menghapusnya, itu bagus.

michael hansen079
sumber