Angular Infinite $digest Loop

Angular Infinite $digest Loop

本文关键字:Loop digest Infinite Angular      更新时间:2023-09-26

我正在一个网站上工作,你可以在那里搜索食物,看看是水果还是蔬菜,或者两者都没有(因为我很无聊(。我决定使用Angular,尽管我对它还很陌生。我开始收到以下错误:$rootScope:infdig无限$digest循环

这可能是确切的措辞或错误,也可能不是,因为页面滞后太多,我无法打开Javascript控制台。

这是我的结果视图控制器:

app.controller('resultController', ['$scope', '$routeParams', '$http',
    function($scope, $routeParams, $http) {
        $scope.result = $routeParams.query;
        $scope.whatIsIt = function() {
            $http.get('json/foods.json').success(function(data) {
                var lists = JSON.parse(data);
                var itIsA = 'uuggghhhhh';
                if (lists['fruit'].contains($scope.result)) {
                    itIsA = 'fruit';
                } else if (lists['vegetable'].contains($scope.result)) {
                    itIsA = 'vegetable';
                }
            });
        }
    }]);

这是我的应用程序模块:

var app = angular.module('fruitOrNot', [
    'ngRoute'
]);
app.config(['$routeProvider' ,
    function($routeProvider) {
        $routeProvider.when('/', {
            templateUrl: 'layouts/fruit-search.html',
            controller: 'searchController'
        }).when('/:query', {
            templateUrl: 'layouts/result.html',
            controller: 'resultController'
        });
    }]);

这里是layouts/result.html:

<h1>{{ result }}</h1>
<p>{{ result }} is a {{ whatIsIt() }}</p>

因此,我想知道是什么原因导致了$digest循环错误,或者如何找出原因,因为我无法使用控制台。谢谢

整个项目也在Github上。

您遇到的问题是在作用域上设置了一个字段,该字段隐式调用$digest并重新布局模板。但是,布局模板会再次发出http请求,然后更改调用$digest的范围。这就是无限循环。

您可以通过确保在模板的布局过程中永远不会触发http请求来避免这种情况。

实现应用程序的一种更为正确的方法是将GET请求提取到适当的服务中,然后将服务注入控制器中。

然后在控制器中,您拨打服务电话,如下所示:

app.controller('resultController', ['$scope', '$routeParams', 'whatsitService',
    function($scope, $routeParams, $http) {
        $scope.result = $routeParams.query;
        whatsitService.doit().then(function(result) {
            $scope.whatsit = result;
        }
    })
;

你的模板看起来像这样:

<h1>{{ result }}</h1>
<p>{{ result }} is a {{ whatsit }}</p>

问题是您试图调用一个函数并直接发布返回值,而您试图返回的值超出了范围。您需要将该值放入范围中。

代码片段:

app.controller('resultController', ['$scope', '$routeParams', '$http',
function($scope, $routeParams, $http) {
    $scope.result = $routeParams.query;
    $scope.itIsA = "";
    $scope.whatIsIt = function() {
        $http.get('json/foods.json').success(function(data) {
            var lists = JSON.parse(data);
            var itIsA = 'uuggghhhhh';
            if (lists['fruit'].contains($scope.result)) {
                $scope.itIsA = 'fruit';
            } else if (lists['vegetable'].contains($scope.result)) {
                $scope.itIsA = 'vegetable';
            }               
        });
    }
}]);

以及在HTML模板中:

p>{{ result }} is a {{itIsA}}</p>

如果您将表达式绑定到以下情况,则可以发生无限$digest循环:{{events()}}

$scope.events = function() { return Recording.getEvents(); }

但在以下情况下则不然。即使您已绑定{{events}}

$scope.events = Recording.getEvents();

原因是在第一个角度中,假设值在每个摘要循环中都在变化,并不断更新。在第二个角度中它只是等待承诺。

发生这种情况是因为中的角度表达式"{{ whatIsIt() }}"{{ result }} is a {{ whatIsIt() }}"您正在调用一个函数,该函数每次调用都会返回不同的值,从而导致一个新的摘要循环,该循环反过来调用该函数。

我认为您应该将whatIsIt()的结果绑定到一个值,然后在模板中使用该值。看看这个https://docs.angularjs.org/error/$rootScope/infdig