141

我有以下代码重复并显示用户的姓名和他的分数:

<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-repeat 内部初始化,并且限制应用于对象的数量。所以我觉得同时拥有 sortby 和 limitTo 观察者是错误的原因。

如果 $scope.reverse 为假(分数升序),则不会出错。

谁能帮我理解这里有什么问题?非常感谢您的帮助。

4

13 回答 13

117

请检查这个jsFiddle。(代码与您发布的代码基本相同,但我使用元素而不是窗口来绑定滚动事件)。

据我所知,您发布的代码没有问题。您提到的错误通常发生在您对属性创建更改循环时。例如,当您观察某个属性的更改,然后在侦听器上更改该属性的值时:

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

这将导致出现错误消息:

未捕获的错误:达到 10 次 $digest() 迭代。中止!
观察者在最后 5 次迭代中被解雇:...

确保您的代码没有这种情况。

更新:

这是你的问题:

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

您不应该在渲染期间更改对象/模型,否则它将强制进行新的渲染(因此导致循环,这会导致“错误:达到 10 $digest() 迭代。中止!”)。

如果要更新模型,请在控制器或指令上进行,不要在视图上进行。angularjs 文档建议不要使用完全ng-init来避免这些情况:

在模板中使用 ngInit 指令(仅适用于玩具/示例应用程序,不推荐用于实际应用程序)

这是一个带有工作示例的jsFiddle 。

于 2013-01-17T14:37:52.113 回答
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);
}
于 2014-11-06T15:57:35.910 回答
7

对我来说,我将函数结果作为 2 路绑定输入“=”传递给每次都创建新对象的指令。

所以我有这样的事情:

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

解决了问题!

希望这会对某人有所帮助:)

于 2016-03-23T17:41:59.427 回答
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);
});
于 2015-06-25T17:13:52.347 回答
2

对于初学者,请忽略所有答案,告诉您使用 $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;
 }
}
});

通过 $index 跟踪 ng-repeat,当数组的长度等于索引时停止循环并执行您的逻辑。

jsfiddle

于 2016-09-20T17:06:16.163 回答
2

派对迟到了,但我的问题正在发生,因为 Angular 1.5.8 中的 ui-router 存在缺陷。值得一提的是,此错误仅在我第一次运行应用程序时出现,之后不会再次出现。 来自github的这篇文章解决了我的问题。基本上错误涉及$urlRouterProvider.otherwise("/home") 解决方案是这样的解决方法:

$urlRouterProvider.otherwise(function($injector, $location) {
   var $state = $injector.get("$state");
   $state.go("your-state-for-home");
});
于 2018-03-09T15:20:14.163 回答
1

这很奇怪......我有完全相同的错误,来自不同的东西。当我创建我的控制器时,我传递了 $location 参数,如下所示:

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

当我们使用第三方库或纯 JS 来操作某些细节(此处为 window.location)时,这被证明是一个错误,下一个 Angular 的摘要将解决这个错误。

所以我只是从控制器创建参数中删除了$location,它再次工作,没有这个错误。或者,如果您绝对需要使用 Angular 中的 $location,则必须删除<a href="#">link</a>模板页面链接中的每个链接,而是编写href=""。为我工作。

希望有一天能有所帮助。

于 2015-06-25T12:38:53.840 回答
1

我在角度树控制的上下文中遇到了这个错误。就我而言,它是树选项。我从一个函数返回 treeOptions() 。它总是返回相同的对象。但是 Angular 神奇地认为它是一个新对象,然后导致一个摘要循环开始。导致摘要的递归。解决方案是将 treeOptions 绑定到范围。并且只分配一次。

于 2018-04-30T15:25:41.373 回答
0

如果您使用 angular 从浏览器控制台中删除 ng-storage 配置文件。这不是一个通用的解决方案位它在我的情况下有效。

在 Chrome 中 F12->资源->本地存储

于 2016-07-27T11:55:25.837 回答
0

这发生在我将 Firefox 升级到 51 版之后。之后clearing the cache,问题就消失了。

于 2017-01-25T08:48:32.373 回答
0

我有类似的错误,因为我已经定义

ng-class="GetLink()"

代替

ng-click="GetLink()"

于 2017-03-11T10:07:53.317 回答
0

当使用 $sce.trustAsResourceUrl() 作为从 ng-src 调用的函数的返回值时,从 angular 1.6 -> 1.7 升级后,这发生在我身上。你可以看到这里提到的这个问题

就我而言,我必须更改以下内容。

<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);
于 2018-10-09T15:32:01.267 回答
0

当我在我的自定义排序过滤器中调用Array.reverse()时,我使用 AngularJS 1.3.9 得到了完全相同的错误

拆掉之后,还不错。

于 2019-11-26T11:34:20.870 回答