Angularjs “如何排除角度故障”;10$digest()迭代次数已达到“;错误

Angularjs “如何排除角度故障”;10$digest()迭代次数已达到“;错误,angularjs,Angularjs,已达到10$digest()迭代次数。流产 有很多支持文本的意思是“在过去5次迭代中触发的观察者:”,等等,但是这些文本中有很多是来自各种函数的Javascript代码。是否有诊断此问题的经验法则?这是一个总是可以缓解的问题,还是有足够复杂的应用程序可以将此问题视为一个警告?通常在每次返回不同对象时都会发生这种情况 例如,如果在ng repeat中使用此选项: $scope.getObj = function () { return [{a: 1}, {b: 2}]; }; 您将得到此错误

已达到10$digest()迭代次数。流产


有很多支持文本的意思是“在过去5次迭代中触发的观察者:”,等等,但是这些文本中有很多是来自各种函数的Javascript代码。是否有诊断此问题的经验法则?这是一个总是可以缓解的问题,还是有足够复杂的应用程序可以将此问题视为一个警告?

通常在每次返回不同对象时都会发生这种情况

例如,如果在
ng repeat
中使用此选项:

$scope.getObj = function () {
  return [{a: 1}, {b: 2}];
};
您将得到此错误消息,因为Angular尝试具有“稳定性”,并将执行函数,直到它返回相同的结果2次(与
==
相比),在我们的示例中,这将永远不会返回true,因为函数始终返回一个新对象

console.log({} === {}); // false. Those are two different objects!
在这种情况下,您可以通过将对象直接存储在作用域中来修复它,例如

$scope.objData = [{a: 1}, {b: 2}];
$scope.getObj = function () {
  return $scope.objData;
};
这样,您总是返回相同的对象

console.log($scope.objData === $scope.objData); // true (a bit obvious...)
(即使在复杂的应用程序中,也不应该遇到这种情况)


更新:Angular。

正如文所说,您要么在每个
$digest
周期返回不同(不完全相同)的对象,要么更改数据太多次

找出导致此行为的应用程序的哪个部分的最快解决方案是:

  • 删除所有可疑HTML-基本上从模板中删除所有HTML,并检查是否没有警告
  • 如果没有警告-添加您删除的html的一小部分,并检查问题是否再次出现
  • 重复步骤2,直到收到警告-您将找出html的哪一部分是问题的原因
  • 进一步调查-步骤3中的部分负责变异
    $scope
    上的对象,或者在每个
    $digest
    周期返回不相同的对象
  • 如果在步骤1之后仍然有
    $digest
    迭代警告,那么您可能正在做一些非常可疑的事情。对父模板/范围/控制器重复相同的步骤
  • 您还需要确保没有更改自定义过滤器的输入

    请记住,在JavaScript中有一些特定类型的对象的行为与您通常期望的不同:

    new Boolean(true) === new Boolean(true) // false
    new Date(0) == new Date(0) // false
    new String('a') == new String('a') // false
    new Number(1) == new Number(1) // false
    [] == [] // false
    new Array == new Array // false
    ({})==({}) // false
    

    我只是想把这个解决方案放在这里,希望它能帮助其他人。我之所以遇到这个迭代问题,是因为我对生成的属性进行了迭代,该属性每次被调用时都会生成一个新对象

    我通过在第一次请求生成的对象时缓存它来修复它,然后总是返回缓存(如果存在)。还添加了dirty()方法,该方法将根据需要销毁缓存的结果

    我有这样的想法:

    function MyObj() {
        var myObj = this;
        Object.defineProperty(myObj, "computedProperty" {
            get: function () {
                var retObj = {};
    
                return retObj;
            }
        });
    }
    
    var date = new Date(); // typeof returns object
    
    <input type="text" ng-model="$ctrl.myObj.C" uib-tooltip-html="$ctrl.myObj.getTooltip().trusted">
    
    下面是实施的解决方案:

    function MyObj() {
        var myObj = this,
            _cached;
        Object.defineProperty(myObj, "computedProperty" {
            get: function () {
                if ( !_cached ) {
                    _cached = {};
                }
    
                return _cached;
            }
        });
    
        myObj.dirty = function () {
            _cached = null;
        }
    }
    

    我也有同样的问题——我每次都在创造一个新的约会。因此,对于任何处理日期的人,我将所有呼叫转换为如下:

    function MyObj() {
        var myObj = this;
        Object.defineProperty(myObj, "computedProperty" {
            get: function () {
                var retObj = {};
    
                return retObj;
            }
        });
    }
    
    var date = new Date(); // typeof returns object
    
    <input type="text" ng-model="$ctrl.myObj.C" uib-tooltip-html="$ctrl.myObj.getTooltip().trusted">
    
    致:


    初始化一个数字而不是日期对象为我解决了这个问题

    这是
    ui路由器中的一个已知错误,这对我们有帮助:

    我还想提到,当我在项目中的自定义指令的templateUrl中输入错误时,我收到了此错误消息。由于输入错误,无法加载模板

    /* @ngInject */
    function topNav() {
        var directive = {
            bindToController: true,
            controller: TopNavController,
            controllerAs: 'vm',
            restrict: 'EA',
            scope: {
                'navline': '=',
                'sign': '='
            },
            templateUrl: 'app/shared/layout/top-navTHIS-IS-A-TYPO.html'
        };
    
    查看web浏览器的“开发工具”的“网络”选项卡,查看是否有任何资源出现404错误


    很容易忽略,因为错误消息非常隐晦,似乎与实际问题无关。

    我在项目中遇到此问题是因为。否则()丢失了我的路由定义,我遇到了错误的路由。

    也有可能它根本不是一个无限循环。10次迭代的数量不足以确定地得出结论。因此,在进行白费力气之前,最好先排除这种可能性

    最简单的方法是将最大摘要循环计数增加到一个更大的数字,这可以通过使用该方法在该方法中完成。如果
    infdig
    错误不再出现,您只需要拥有一些足够复杂的更新逻辑

    如果您使用递归监视构建数据或视图,您可能希望使用
    while
    for
    Array.forEach
    搜索迭代解决方案(即不依赖要启动的新摘要循环)。有时,结构只是高度嵌套的,甚至不是递归的,在这些情况下,除了提高限制之外,可能没有什么可以做的

    调试错误的另一种方法是查看摘要数据。如果您漂亮地打印JSON,您将得到一个数组数组。每个顶级条目代表一个迭代,每个迭代由一个监视条目列表组成

    例如,如果您有一个在
    $watch
    中修改的属性,则很容易看到该值正在无限变化:

    $scope.vm.value1 = true;
    $scope.$watch("vm.value1", function(newValue)
    {
        $scope.vm.value1 = !newValue;
    });
    
    当然,在更大的项目中,这可能没有那么简单,特别是因为如果手表是
    {}
    插值,那么
    msg
    字段通常具有值
    “fn:regulationInterceptedExpression”


    除此之外,前面提到的方法,如减少HTML以找到问题的根源,当然是有帮助的。

    我之所以遇到这个问题,是因为我正在这样做

    var variableExpense = this.lodash.find(product.variableExpenseList, (ve) => {
                   return ve.rawMaterial.id = rawMaterial.id;
    });
    
    相反:(notice=vs==),我的单元测试开始崩溃,我发现自己很愚蠢

    var variableExpense = this.lodash.find(product.variableExpenseList, (ve) => {
                   return ve.rawMaterial.id === rawMaterial.id;
    });
    
    简单的方法是: 使用angular.js,而不是min文件。 打开它并找到行:

    if ((dirty || asyncQueue.length) && !(ttl--)) {
    
    在下面添加行:

    console.log("aaaa",watch)
    
    然后刷新页面,在developetools控制台中,您将
    查找错误代码。

    我遇到了这个问题,需要一个动态工具提示。。。它导致angular每次都将其作为新值重新计算(即使它是相同的)。我创造
    Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!