Angular JS: IE Error: 10 $digest() iterations reached. Aborting

I'm new to Angular and I'm stuck with a issue relating IE.

Here is the IE Error that I'm getting.

Webpage error details

User Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
Timestamp: Thu, 13 Dec 2012 04:00:46 UTC


Message: 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: [["fn: function $locationWatch() {\n      var oldUrl = $browser.url();\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n\tchangeCounter++;\n\t$rootScope.$evalAsync(function() {\n\t  if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n\t      defaultPrevented) {\n\t    $location.$$parse(oldUrl);\n\t  } else {\n\t    $browser.url($location.absUrl(), $location.$$replace);\n\t    $location.$$replace = false;\n\t    afterLocationChange(oldUrl);\n\t  }\n\t});\n      }\n\n      return changeCounter;\n    }; newVal: 7; oldVal: 6"],["fn: function $locationWatch() {\n      var oldUrl = $browser.url();\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n\tchangeCounter++;\n\t$rootScope.$evalAsync(function() {\n\t  if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n\t      defaultPrevented) {\n\t    $location.$$parse(oldUrl);\n\t  } else {\n\t    $browser.url($location.absUrl(), $location.$$replace);\n\t    $location.$$replace = false;\n\t    afterLocationChange(oldUrl);\n\t  }\n\t});\n      }\n\n      return changeCounter;\n    }; newVal: 8; oldVal: 7"],["fn: function $locationWatch() {\n      var oldUrl = $browser.url();\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n\tchangeCounter++;\n\t$rootScope.$evalAsync(function() {\n\t  if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n\t      defaultPrevented) {\n\t    $location.$$parse(oldUrl);\n\t  } else {\n\t    $browser.url($location.absUrl(), $location.$$replace);\n\t    $location.$$replace = false;\n\t    afterLocationChange(oldUrl);\n\t  }\n\t});\n      }\n\n      return changeCounter;\n    }; newVal: 9; oldVal: 8"],["fn: function $locationWatch() {\n      var oldUrl = $browser.url();\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n\tchangeCounter++;\n\t$rootScope.$evalAsync(function() {\n\t  if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n\t      defaultPrevented) {\n\t    $location.$$parse(oldUrl);\n\t  } else {\n\t    $browser.url($location.absUrl(), $location.$$replace);\n\t    $location.$$replace = false;\n\t    afterLocationChange(oldUrl);\n\t  }\n\t});\n      }\n\n      return changeCounter;\n    }; newVal: 10; oldVal: 9"],["fn: function $locationWatch() {\n      var oldUrl = $browser.url();\n\n      if (!changeCounter || oldUrl != $location.absUrl()) {\n\tchangeCounter++;\n\t$rootScope.$evalAsync(function() {\n\t  if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).\n\t      defaultPrevented) {\n\t    $location.$$parse(oldUrl);\n\t  } else {\n\t    $browser.url($location.absUrl(), $location.$$replace);\n\t    $location.$$replace = false;\n\t    afterLocationChange(oldUrl);\n\t  }\n\t});\n      }\n\n      return changeCounter;\n    }; newVal: 11; oldVal: 10"]]
Line: 7859
Char: 6
Code: 0
URI: http://localhost:8080/__assets__/lib/angular/angular.js

This is not happening in any other browser but IE 8 and IE 9.

I have a watch looking at a content filtering object which includes a location filter.

My question with this is why doesn't it happen on any other browser but IE and what should I do to get rid of this. Thanks in advance.

Answers:

Answer

I had the same issue with error which looked the same. Chrome\FF worked fine, but IE failed. I've clicked on some links in my app and sometimes got this error and sometimes not.

1) In my view I had few links which looked like this:

<a href="#" ng-click="addIP(ip)">Add some IP</a>

2) Click handler for those links added new object into IpRanges collection like this:

$scope.IpRanges.push(ip);

3) Collection itself was binded on view by ng-repeat, and I thought that somehow IE could not handle this situation well - probably order of binding\adding\applying events wasn't incorrect or else... Also after click on links I had # symbol added to url, and sometimes it blinked, and then I've got an error. So I removed href attribute and everything worked fine:

<a href="" ng-click="addCurrentIP()">Add as allowed IP</a>

Probably it's better to use spans or divs for similar situations.

Answer

Tiago Roldão is definitely right. I had exact the same issue. After debug, I realized in my code I have

location.hash = "#/app/" + id;

which causes the infinitely loop issue. After some research, I found this

$location.path("/apps/" + id);

which solves my issue perfectly.

Answer

I had the same issue using AngularJS v1.2.13 in IE9, IE10, when calling $window.history.back() (especially in Windows Phone).

It seems the root cause is that $window.history.back() in IE changes the href right before the $locationWatch() is fired hence oldUrl would contain the new Url and that throws off the angular into an infinite $digest.

The immediate work around is to replace the calls to $window.history.back() with the following:

setTimeout(function () 
{
    $window.history.back();
}, 0);
Answer

I can tell from your error report you have a $watch for a changeCounter variable, and this watcher function:

function $locationWatch() {
    var oldUrl = $browser.url();
    if (!changeCounter || oldUrl != $location.absUrl()) {
        changeCounter++;
        $rootScope.$evalAsync(function () {
            if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl)
                .defaultPrevented) {
                $location.$$parse(oldUrl);
            } else {
                $browser.url($location.absUrl(), $location.$$replace);
                $location.$$replace = false;
                afterLocationChange(oldUrl);
            }
        });
    }
    return changeCounter;
};

And the changeCounter gets it's value incremented if $browser.url() doesn't equal $location.absUrl(). As the $watch function can only do 10 loops of change/reaction, it will err after those 10 iterations. As you are changing the value you are watching, it eventually breaks.

I would log those values - $location.absUrl() and $browser.url(), and see why the match in other browsers, but not in ie.

Answer

I was facing issue in IE 10. I was using

window.location.href = '#/';

for changing the route. Replacing it with below code

$location.path('/');

resolved the issue

Answer

TLDR

If you are using ui-router then you can also use

$state.go('details', {id:item.ID});

Background

I was using the following function to navigate from a list view to a details view so that you can click anything with ng-click="details(item)", in my case tr's in the list:

$scope.details = function (item) {
    $window.location.href = "#/details/" + item.ID;
}

But I was getting the dreaded 10 $digest() iterations reached in IE.

FYI

I placed a breakpoint in AngularJS v1.2.0rc1 angular.js line 7650 following Tiago's answer.

// update browser
var changeCounter = 0;
$rootScope.$watch(function $locationWatch() {
  var oldUrl = $browser.url();
  var currentReplace = $location.$$replace;

  if (!changeCounter || oldUrl != $location.absUrl()) {
    changeCounter++; /* <-- breakpoint here, line 7650 */
    $rootScope.$evalAsync(function() {
      if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl).
          defaultPrevented) {
        $location.$$parse(oldUrl);
      } else {
        $browser.url($location.absUrl(), currentReplace);
        afterLocationChange(oldUrl);
      }
    });
  }
  $location.$$replace = false;

  return changeCounter;
});

Results

Output from Chrome

  • The breakpoint was only hit once the details page was loading and once only.
  • oldUrl (i.e. $browser.url() was reporting the old url (i.e. the list one)
  • $location.absUrl() was reporting the details url.

Output from IE7,8

  • The breakpoint was hit continuously.
  • oldUrl (i.e. $browser.url() was reporting the new url (i.e. the details one)
  • $location.absUrl() was still reporting the list url.
Answer

I had this problem when trying to redirect to other page as

$window.location.href = '#/path/'

solved by changing to:

$location.path('/path/');

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.