错误:达到$ $ digest()迭代.中止!使用动态排序谓词

Sab*_*kar 133 javascript-framework angularjs

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

<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>
Run Code Online (Sandbox Code Playgroud)

和相应的角度控制器.

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'}]
}
Run Code Online (Sandbox Code Playgroud)

当我运行上面的代码时,我得到Error:10 $ digest()迭代.中止!我的控制台出错了.

我已经创建了同样的jsfiddle.

排序谓词仅在ng-repeat内部初始化,并且限制也应用于对象的数量.所以我觉得将sortby和limitTo观察者放在一起就是出错的原因.

如果$ scope.reverse为false(得分的升序),那么它不会出错.

任何人都可以帮我理解这里有什么问题吗?非常感谢你的帮助.

bml*_*ite 114

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

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

$scope.$watch('users', function(value) {
  $scope.users = [];
});
Run Code Online (Sandbox Code Playgroud)

这将导致错误消息:

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

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

更新:

这是你的问题:

<div ng-init="user.score=user.id+1"> 
Run Code Online (Sandbox Code Playgroud)

你不应该在渲染过程中更改对象/模型,否则它将强制一个新的渲染(因此循环,导致'错误:10 $ digest()迭代到达.中止!').

如果要更新模型,请在Controller或指令上执行,而不要在视图上执行.angularjs文件建议不使用ng-init完全相同,以避免这些种情况:

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

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


Nat*_*at8 9

造成这个错误的原因是......

ng-if="{{myTrustSrc(chat.src)}}"
Run Code Online (Sandbox Code Playgroud)

在我的模板中

它导致我的控制器中的函数myTrustSrc在无限循环中被调用.如果我从此行中删除ng-if,则问题就解决了.

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

当不使用ng-if时,该函数仅被调用几次.我仍然想知道为什么使用ng-src多次调用该函数?

这是控制器中的功能

$scope.myTrustSrc = function(src) {
    return $sce.trustAsResourceUrl(src);
}
Run Code Online (Sandbox Code Playgroud)


Mic*_*dis 6

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

所以我有这样的事情:

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

而my-dir上的控制器方法是

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

当我做了

this.convertToSomeOtherObject(entity) {
   var converted = entity;
   converted.id = entity.Id;
   converted.value = entity.Value;
   [...]
   return converted;
}
Run Code Online (Sandbox Code Playgroud)

解决了问题!

希望这会帮助某人:)


squ*_*man 5

我有另一个导致这种情况的例子。希望它对将来的参考有所帮助。我正在使用AngularJS 1.4.1。

我有多次调用自定义指令的标记:

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

myData是一个数组,并且Where()是一个扩展方法,它在该数组上进行迭代,返回一个新数组,该数组包含IsOpen属性与第二个参数中的bool值匹配的原始项。

在控制器中,我这样设置$scope.data

DataService.getData().then(function(results){
    $scope.data = results;
});
Run Code Online (Sandbox Code Playgroud)

问题是Where()从指令中调用扩展方法,就像上面的标记一样。要解决此问题,我将对扩展方法的调用移到了控制器中,而不是在标记中:

<div ng-controller="SomeController">
    <myDirective data="openData"></myDirective>
    <myDirective data="closedData"></myDirective>
</div>
Run Code Online (Sandbox Code Playgroud)

和新的控制器代码:

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