【问题标题】:AngularJS: Error: [$rootScope:infdig] - Call function in AngularJS viewAngularJS:错误:[$rootScope:infdig] - 在 AngularJS 视图中调用函数
【发布时间】:2018-01-30 14:43:27
【问题描述】:

我写了一个包含这个功能的控制器:

$scope.getItemName = function (id) {
    sgcdata.get('item', {
        _id: id
    }).then(function (dataItem) {
        return dataItem[0].brand_name + " " + dataItem[0].reference;
    });
}

在视图中:

<li ng-repeat="itemCart in connectedUser.cart track by $index" class="list-group-item">
     <span class="badge cursorpointer" ng-click="removeFromCart(itemCart)">X</span>
     <a href="#">{{ getItemName(itemCart) }}</a>
</li>

当我这样做时,我得到一个无限循环 ($rootScope:infdig)。

sgcdata.get 发出 XHR 请求。

但是如果我返回一个简单的字符串,它就可以工作:

$scope.getItemName = function (id) {
    return "toto";
}

我真的不明白发生了什么......

感谢您的帮助。

编辑

我做了一个过滤器而不是之前的函数:

JS:

sgc.filter('getItemName', [
    'sgcdata',
    function (sgcdata) {
        return function (id) {
            sgcdata.get('item', {
                _id: id
            }).then(function (dataItem) {
                return dataItem[0].brand_name + " " + dataItem[0].reference;
            });
        }
    }
]);

HTML:

<li ng-repeat="itemCart in connectedUser.cart track by $index" class="list-group-item">
    <span class="badge cursorpointer" ng-click="removeFromCart(itemCart)">X</span>
    <a href="#">{{ itemCart | getItemName }}</a>
</li>

我不再有任何无限循环,但我无法在 ng-repeat 中获取多个值,而过滤器返回在项目请求中。

编辑

sgcdata.get:

service.get = function (collection, filters) {
    var deferred = $q.defer();
    var formatRequest = function (obj) {
        var str = [];
        for (var p in obj) {
            str.push(encodeURIComponent(p) + '=' + encodeURIComponent(obj[p]));
        }
        if (str.length) {
            return '&' + str.join('&');
        } else {
            return '';
        }
    };
    $http({
        method: 'GET',
        url: '/v1/get/?element=' + collection.toLowerCase() + formatRequest(filters)
    }).then(function (response) {
        deferred.resolve(response.data);
    }, function (response) {
        console.error("[ FAILED ] >> " + response);
    });
    return deferred.promise;
}

【问题讨论】:

  • 您绑定一个值,该值将解析为触发摘要循环的内容。该循环将尝试再次解析该值并触发另一个摘要等等......只是不要绑定函数!
  • sgcdata 一个 Promise ($q / $http)?
  • @AlekseySolovey 是的。
  • @FrançoisRousselet 它不会返回一个值,而是一个 Promise instead
  • @FrançoisRousselet $http 已经返回了一个promise,不需要使用$q,这是一个anti-pattern

标签: javascript angularjs angularjs-scope angular-http angularjs-infdig


【解决方案1】:

由于摘要循环本身的性质,从ng-repeat HTML 模板中调用函数总是会导致Infinite Digest 错误。

基本上,ng-repeat 尝试渲染子节点。在子节点中,您正在调用一个函数,这会导致摘要发生。这个新的摘要会导致ng-repeat 重新开始,这会导致子节点再次运行,从而导致另一个摘要,无穷无尽。

有几种普遍接受的方法来处理这个问题,每种方法都有自己的优缺点。

  1. 从服务器获取原始数组时,在服务器上执行逻辑以将所有相关字段包含在原始返回值中。这是非常高效的,因为您允许您的服务器完成所有繁重的工作,并且只需一次调用服务器。但是,您可能会发送仅对应用的一小部分有用的额外数据,这可能会减慢初始启动时间。

  2. 在获取原始数组时,对返回的每个元素运行该函数,以将额外数据添加为每个元素的新属性。这是相当有效的,因为这意味着您的所有数据都是预先加载的,您只需对每个元素进行一次额外的调用。这可能会遭受与您发送不常用数据相同的负面影响,如果您有许多元素要迭代,这也可能会放大初始启动速度。

  3. 将过滤器添加到ng-repeat,而不是元素,它遍历数组并专门获取ng-repeat 的额外数据。这样做的好处是仅在存在ng-repeat 时才对服务器进行额外调用,并且不会将额外数据添加到原始数组中。但是,这些对服务器的额外调用将​​在ng-repeat 更改(添加新元素、删除项目、应用其他过滤器等)时执行,这可能会导致严重的性能损失,具体取决于数据量和频率变化。

【讨论】:

    【解决方案2】:

    您应该从函数返回相同的引用或值。否则事情会失控。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-20
      • 1970-01-01
      • 1970-01-01
      • 2016-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多