Lỗi: 10 lần lặp digest () đạt được. Hủy bỏ! với vị ngữ sắp xếp động


134

Tôi có đoạn mã sau lặp lại và hiển thị tên của người dùng và điểm của anh ấy:

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

Và bộ điều khiển góc tương ứng.

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

Khi tôi chạy đoạn mã trên, tôi nhận được các lỗi lặp: 10 $ digest (). Hủy bỏ! lỗi trong giao diện điều khiển của tôi.

Tôi đã tạo jsfiddle cho cùng.

Vị từ sắp xếp chỉ được khởi tạo bên trong ng-repeat và giới hạn đang được áp dụng cho số lượng đối tượng. Vì vậy, tôi cảm thấy có cả người theo dõi và giới hạn Để người theo dõi cùng nhau là lý do cho lỗi.

Nếu $ scope.reverse là sai (thứ tự tăng dần của điểm số), thì nó không bị lỗi.

Bất cứ ai có thể giúp tôi hiểu những gì sai ở đây? Rất đánh giá cao sự giúp đỡ của bạn.


Nếu bạn loại bỏ câu lệnh if, nó vẫn có lỗi không?
Mathew Berg

Cảm ơn bạn đã trả lời Mathew! Tôi chẩn đoán sai vấn đề. Vấn đề dường như là với các bộ lọc sắp xếp và giới hạn. Tôi đã cập nhật câu hỏi với JSFiddle. Rất đánh giá cao sự giúp đỡ của bạn.
Cậu bé mũm mĩm

đây là một điều góc cạnh Bạn cần ghi nhớ các chức năng của bạn và sau đó ghi nhớ trạng thái. Hãy xem câu trả lời của tôi trên stackoverflow.com/questions/14376879/ từ
Julio Marins

Câu trả lời:


116

Vui lòng kiểm tra jsFiddle này . (Mã về cơ bản giống như bạn đã đăng nhưng tôi sử dụng một yếu tố thay vì cửa sổ để liên kết các sự kiện cuộn).

Theo như tôi có thể thấy, không có vấn đề gì với mã bạn đã đăng. Lỗi bạn đề cập thường xảy ra khi bạn tạo một vòng thay đổi trên một thuộc tính. Ví dụ, như khi bạn xem các thay đổi trên một thuộc tính nhất định và sau đó thay đổi giá trị của thuộc tính đó trên trình nghe:

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

Điều này sẽ dẫn đến một thông báo lỗi:

Uncaught Error: 10 $ digest () lần lặp đạt được. Hủy bỏ!
Những người theo dõi bị sa thải trong 5 lần lặp lại gần đây: ...

Hãy chắc chắn rằng mã của bạn không có loại tình huống này.

cập nhật:

Đây là vấn đề của bạn:

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

Bạn không nên thay đổi các đối tượng / mô hình trong quá trình kết xuất hoặc nếu không, nó sẽ buộc kết xuất mới (và do đó là một vòng lặp , điều này gây ra các lỗi lặp 'Lỗi: 10 $ digest (). Hủy bỏ!' ).

Nếu bạn muốn cập nhật mô hình, hãy thực hiện trên Bộ điều khiển hoặc trên Chỉ thị, không bao giờ trên chế độ xem. tài liệu angularjs khuyến cáo không nên sử dụng các ng-initchính xác để tránh những loại tình huống:

Sử dụng chỉ thị ngInit trong các mẫu (chỉ dành cho ứng dụng đồ chơi / ví dụ, không được khuyến nghị cho các ứng dụng thực tế)

Đây là một jsFiddle với một ví dụ hoạt động.


1
FYI, thay vì angular.element(w).bind()bạn có thể sử dụng element.bind().
Mark Rajcok

Cảm ơn nhiều bmleite và Mark. Tôi chẩn đoán sai vấn đề. Xin vui lòng xem ý kiến ​​của tôi ở trên. Tôi đã cập nhật câu hỏi với JSFiddle. Rất đánh giá cao sự giúp đỡ của bạn.
Cậu bé mũm mĩm

Cảm ơn rất nhiều @bmleite! Chỉ cần cố gắng để hiểu thêm. Nhưng tại sao nếu $ scope.reverse = false (thứ tự tăng dần của điểm số) không gây ra lỗi?
Cậu bé mũm mĩm

Để tăng dần và giảm dần, bạn nên sử dụng các tiền tố '+' và '-', tương ứng (nghĩa là '+ điểm' và '-score'). Thêm thông tin về điều này ở đây .
bmleite

1
Câu trả lời này đã giải quyết vấn đề của tôi. Giải thích tốt ở chỗ nó mô tả vấn đề: lỗi lặp lại $ digest () khi bạn cố gắng sửa đổi một thuộc tính cùng lúc bạn đang lặp lại. Vì vậy, mỗi thay đổi thuộc tính kích hoạt một bản cập nhật của chế độ xem (UI) và góc cuối cùng đạt tối đa 10 vòng. Ví dụ jsFiddle đặt thay đổi thuộc tính trong Bộ điều khiển. Thay đổi thuộc tính trong Xem kết quả trong lỗi này.
mbokil

9

Nguyên nhân của lỗi này đối với tôi là ...

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

trong mẫu của tôi

Nó làm cho hàm myTrustSrc trong bộ điều khiển của tôi được gọi trong một vòng lặp vô tận. Nếu tôi loại bỏ ng-if khỏi dòng này, thì vấn đề đã được giải quyết.

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

Hàm chỉ được gọi một vài lần khi ng-if không được sử dụng. Tôi vẫn tự hỏi tại sao hàm được gọi nhiều hơn một lần với ng-src?

Đây là chức năng trong bộ điều khiển

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

Tôi vẫn tự hỏi tại sao hàm được gọi nhiều hơn một lần với ng-src? - bởi vì angular cố gắng tạo html một vài lần cho đến khi nhận được 2 kết quả giống hệt nhau. đó là ý nghĩa của lỗi lặp lại $ 10 digest (), anh ta đã thử 10 lần và không bao giờ có được 2 kết quả giống hệt nhau
bresleveloper

@bresleveloper bạn có thể cung cấp một liên kết với thông tin này? Cảm ơn.
Willa

@Willa xem tại đây docs.angularjs.org/api/ng/type/$rootScope.Scope CTRF + F này "Giới hạn lặp lại chạy lại là 10 để ngăn chặn bế tắc vòng lặp vô hạn"
bresleveloper 24/8/2015

Cảm ơn. Điều đó đã giúp.
Willa

7

Đối với tôi, đó là tôi đã chuyển một kết quả hàm là đầu vào ràng buộc 2 chiều '=' cho một lệnh tạo ra một đối tượng mới mỗi lần.

Vì vậy, tôi đã có một cái gì đó như thế:

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

và phương thức điều khiển trên my-dir là

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

mà khi tôi làm

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

Đã giải quyết vấn đề!

Hy vọng điều này sẽ giúp được ai đó :)


5

Tôi có một ví dụ khác về một cái gì đó gây ra điều này. Hy vọng nó sẽ giúp tham khảo trong tương lai. Tôi đang sử dụng AngularJS 1.4.1.

Tôi đã có đánh dấu này với nhiều cuộc gọi đến một lệnh tùy chỉnh:

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

myDatalà một mảng và Where()là một phương thức mở rộng lặp đi lặp lại trên mảng trả về một mảng mới chứa bất kỳ mục nào từ bản gốc trong đó thuộc tính IsOpen khớp với giá trị bool trong tham số thứ hai.

Trong bộ điều khiển tôi đặt $scope.datanhư thế này:

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

Gọi Where()phương thức mở rộng từ chỉ thị như trong đánh dấu ở trên là vấn đề. Để khắc phục sự cố này, tôi đã chuyển cuộc gọi sang phương thức mở rộng vào bộ điều khiển thay vì đánh dấu:

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

và mã điều khiển mới:

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

Nghe có vẻ chính xác như vấn đề tôi có. Một hàm đơn giản không cập nhật bất cứ thứ gì, nhưng đã tạo ra một mảng cục bộ, lặp lại trên một mảng $ scope hiện có và tạo các đối tượng trong mảng cục bộ và trả về. Bằng cách gọi một lần và lưu trữ nó trong một thành viên $ phạm vi, nó giải quyết vấn đề. Cảm ơn. Ước gì tôi biết vấn đề với việc sử dụng phương pháp trực tiếp là gì.
AgilePro 7/12/2015

2

Khá muộn cho bữa tiệc nhưng vấn đề của tôi đã xảy ra vì có một khiếm khuyết trong bộ định tuyến ui ở góc 1.5.8. Một điều cần đề cập là lỗi này chỉ xuất hiện lần đầu tiên khi tôi chạy ứng dụng và nó sẽ không xảy ra sau đó. Bài đăng này từ github đã giải quyết vấn đề của tôi. Về cơ bản lỗi liên quan đến $urlRouterProvider.otherwise("/home") Giải pháp là một cách giải quyết như sau:

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

2

Đối với người mới bắt đầu bỏ qua tất cả các câu trả lời với bảo bạn sử dụng $ watch. Angular làm việc của một người nghe đã. Tôi đảm bảo với bạn rằng bạn đang làm phức tạp mọi thứ bằng cách chỉ nghĩ theo hướng này.

Bỏ qua tất cả các câu trả lời cho bạn biết với người dùng $ timeout. Bạn không thể biết trang sẽ tải trong bao lâu, do đó đây không phải là giải pháp tốt nhất.

Bạn chỉ cần biết khi trang được hoàn thành kết xuất.

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

Theo dõi ng-repeat bằng $ index và khi độ dài của mảng bằng chỉ mục dừng vòng lặp và thực hiện logic của bạn.

jsfiddle


1

Tôi đã nhận được lỗi này trong bối cảnh kiểm soát cây góc cạnh. Trong trường hợp của tôi, đó là các tùy chọn cây. Tôi đã trả về treeOptions () từ một hàm. Nó luôn luôn trả lại cùng một đối tượng. Nhưng Angular kỳ diệu nghĩ rằng đó là một vật thể mới và sau đó gây ra một chu kỳ tiêu hóa để khởi động. Gây ra một đệ quy của tiêu hóa. Giải pháp là liên kết các TreeOptions với phạm vi. Và chỉ định nó một lần.


1

Thật kỳ lạ ... Tôi đã có cùng một lỗi, đến từ một điều khác. Khi tôi tạo bộ điều khiển của mình, tôi đã chuyển tham số $ location, như thế này:

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

Điều này đã được chứng minh là một lỗi khi chúng tôi sử dụng các thư viện của bên thứ ba hoặc JS thuần túy để thao tác một số chi tiết cụ thể (ở đây window.location), bản tóm tắt tiếp theo của góc sẽ thổi lỗi này.

Vì vậy, tôi chỉ cần loại bỏ vị trí $ khỏi tham số tạo bộ điều khiển và nó hoạt động trở lại, không có lỗi này. Hoặc nếu bạn thực sự cần sử dụng vị trí $ từ góc, bạn phải xóa từng <a href="#">link</a>liên kết trong trang mẫu của mình và thay vào đó hãy viết href = "" . Đã làm cho tôi.

Hy vọng nó có thể giúp một ngày.



0

Điều này đã xảy ra với tôi ngay sau khi nâng cấp Firefox lên phiên bản 51. Sau đó clearing the cache, vấn đề đã biến mất.


0

tôi đã có lỗi tương tự, bởi vì tôi đã xác định

ng-class = "GetLink ()"

thay vì

ng-click = "GetLink ()"


0

Điều này đã xảy ra với tôi sau khi nâng cấp từ góc 1.6 -> 1.7 khi sử dụng $ sce.trustAsResourceUrl () làm giá trị trả về của hàm được gọi từ ng-src. Bạn có thể thấy vấn đề này được đề cập ở đây .

Trong trường hợp của tôi, tôi đã phải thay đổi như sau.

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

đến

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

0

Tôi đã nhận được cùng một lỗi chính xác khi sử dụng AngularJS 1.3.9 khi tôi, trong bộ lọc sắp xếp tùy chỉnh của mình đã gọi Array.reverse ()

Sau khi tôi gỡ bỏ nó, nó sẽ rất tốt.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.