Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Infinite loop of $locationWatch #2815

Closed
JensRantil opened this issue May 29, 2013 · 31 comments
Closed

Infinite loop of $locationWatch #2815

JensRantil opened this issue May 29, 2013 · 31 comments

Comments

@JensRantil
Copy link
Contributor

I sent an initial e-mail to the Google Groups mailing list here: https://groups.google.com/forum/?fromgroups#!searchin/angular/$24locationWatch/angular/Vihjqr04UUw/f3vIBtk9-IIJ I decided to create an issue to get this thing documented properly.

I have two AngularJS applications that individually functions correctly. One of them uses a $routeProvider to switch between views and the other does not. I just ran into a bug when having both applications on a single page; Switching from http://myurl.com/page.html#/one to http://myurl.com/page.html#/two triggers an infinite loop of $locationWatch calls. Initially loading the page works fine.

I am getting errors similar to #1417, but there are some differences:

  • I am having this issue in Chromium, but many mention that that issue is an IE issue.
  • I am not doing any history.pushStates. My location change is simply done by clicking on an <a href="#/two">link</a> tag.
  • my digest cycle does never finish instead a new $digest cycle is initiated when the previous one has been aborted (it says "Aborting!" in the log over and over again). Here's an extract from my console log:
Error: 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: "[[\"fn: $locationWatch; newVal: 8; oldVal: 7\"], [\"fn: $locationWatch; newVal: 9; oldVal: 8\"], [\"fn: $locationWatch; newVal: 10; oldVal: 9\"], [\"fn: $locationWatch; newVal: 11; oldVal: 10\"], [\"fn: $locationWatch; newVal: 12; oldVal: 11\"]]"
    at Error (<anonymous>)
    at Object.Scope.$digest (http://192.168.147.25:8082/js/angularjs/angular-1.0.6.js:7925:19)
    at Object.Scope.$apply (http://192.168.147.25:8082/js/angularjs/angular-1.0.6.js:8097:24)
    at http://192.168.147.25:8082/js/angularjs/angular-1.0.6.js:9420:36
    at completeOutstandingRequest (http://192.168.147.25:8082/js/angularjs/angular-1.0.6.js:3001:10)
    at http://192.168.147.25:8082/js/angularjs/angular-1.0.6.js:3281:7 angular-1.0.6.js:5704
Uncaught Error: 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: "[[\"fn: $locationWatch; newVal: 8; oldVal: 7\"], [\"fn: $locationWatch; newVal: 9; oldVal: 8\"], [\"fn: $locationWatch; newVal: 10; oldVal: 9\"], [\"fn: $locationWatch; newVal: 11; oldVal: 10\"], [\"fn: $locationWatch; newVal: 12; oldVal: 11\"]]" angular-1.0.6.js:7925
Error: 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: "[[\"fn: $locationWatch; newVal: 19; oldVal: 18\"], [\"fn: $locationWatch; newVal: 20; oldVal: 19\"], [\"fn: $locationWatch; newVal: 21; oldVal: 20\"], [\"fn: $locationWatch; newVal: 22; oldVal: 21\"], [\"fn: $locationWatch; newVal: 23; oldVal: 22\"]]"
    at Error (<anonymous>)
    at Object.Scope.$digest (http://192.168.147.25:8082/js/angularjs/angular-1.0.6.js:7925:19)
    at Object.Scope.$apply (http://192.168.147.25:8082/js/angularjs/angular-1.0.6.js:8097:24)
    at http://192.168.147.25:8082/js/angularjs/angular-1.0.6.js:9420:36
    at completeOutstandingRequest (http://192.168.147.25:8082/js/angularjs/angular-1.0.6.js:3001:10)
    at http://192.168.147.25:8082/js/angularjs/angular-1.0.6.js:3281:7 angular-1.0.6.js:5704
Uncaught Error: 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: "[[\"fn: $locationWatch; newVal: 19; oldVal: 18\"], [\"fn: $locationWatch; newVal: 20; oldVal: 19\"], [\"fn: $locationWatch; newVal: 21; oldVal: 20\"], [\"fn: $locationWatch; newVal: 22; oldVal: 21\"], [\"fn: $locationWatch; newVal: 23; oldVal: 22\"]]" 

Some additional information:

  • AngularJS version: 1.0.6.
  • The other app does not use $route, $routeParams or $location directly. It does, however, use AngularUI, that uses $location. I've tried inactivating AngularUI, but am still getting getting the loop.
  • I know there are reported bugs when doing things like this in html5 mode. I am not using html5 mode.
  • Monkeypatching the $locationWatch to print to console, I notice that old value constantly is "http://myurl.com/page.html#/one" and new value constantly is "http://myurl.com/page.html#/two".
  • I also notice that browser location bar is not changing while the loop is running.
  • I am using Chromium 25.0.1364.160 Ubuntu 10.04.

I've tried recreating this issue, but have so far failed: http://plnkr.co/edit/YSAHIocwCePqg8ZZig11

@JensRantil
Copy link
Contributor Author

@dbinit Proposed I'd try the workaround

angular.module('myApp', []).value('$anchorScroll', null);

mentioned here. It did not work. Instead, I am getting another exception:

TypeError: object is not a function
    at update (http://192.168.147.25:8082/js/angularjs/angular-1.0.6.js:14123:11)
    at Object.Scope.$broadcast (http://192.168.147.25:8082/js/angularjs/angular-1.0.6.js:8261:28)
    at http://192.168.147.25:8082/js/angularjs/angular-1.0.6.js:7417:26
    at wrappedCallback (http://192.168.147.25:8082/js/angularjs/angular-1.0.6.js:6797:59)
    at wrappedCallback (http://192.168.147.25:8082/js/angularjs/angular-1.0.6.js:6797:59)
    at http://192.168.147.25:8082/js/angularjs/angular-1.0.6.js:6834:26
    at Object.Scope.$eval (http://192.168.147.25:8082/js/angularjs/angular-1.0.6.js:8011:28)
    at Object.Scope.$digest (http://192.168.147.25:8082/js/angularjs/angular-1.0.6.js:7876:25)
    at Object.Scope.$apply (http://192.168.147.25:8082/js/angularjs/angular-1.0.6.js:8097:24)
    at done (http://192.168.147.25:8082/js/angularjs/angular-1.0.6.js:9111:20) 

@JensRantil
Copy link
Contributor Author

#1417 (comment) proposes that adding / to the $routeProvider would fix something. It did not.

@JensRantil
Copy link
Contributor Author

I can also recreate this in Firefox 19.0.2.

@JensRantil
Copy link
Contributor Author

This is my $routeProvider:

angular.module('addressbook', [])
  .config(['$routeProvider', function($routeProvider) {
    $routeProvider
      .when('/colleagues', {
        templateUrl: 'partials/addressbook/colleagues.jsp',
        controller: ColleaguesListController
      })
      .when('/colleagues/:contactId', {
        templateUrl: 'partials/addressbook/colleagues.jsp',
        controller: ColleaguesListController
      })
      .when('/external', {
        templateUrl: 'partials/addressbook/externalcontacts.jsp',
        controller: ExternalContactsListController
      })
      .when('/external/:contactId', {
        templateUrl: 'partials/addressbook/externalcontacts.jsp',
        controller: ExternalContactsListController
      })
      .when('/contacts/:contactId', {
        controller: ContactsForwardingController,
        template: "Forwarding you to the right contact..."
      })
      .otherwise({redirectTo: '/colleagues'});
  }])
...

Loading the page with the otherwise(...) case triggered, also triggers the bug.

@JensRantil
Copy link
Contributor Author

I have now isolated what triggers the $locationWatch. The piece of code is:

<div data-ng-controller="MyVoicemailController" data-ng-include src="'/partials/desktopimitation/voicemail.jsp'">
</div>

I also set the content of /partials/desktopimitation/voicemail.jsp to something very static to make sure that it wasn't in fact the underlying partial that was broken.

I'll see if I can reproduce this in a minimum viable example.

@JensRantil
Copy link
Contributor Author

<div data-ng-controller="MyVoicemailController" data-ng-include src="'/partials/desktopimitation/voicemail.jsp'">
</div>

I inlining /partials/desktopimitation/voicemail.jsp in my HTML file was a successful workaround.

@JensRantil
Copy link
Contributor Author

I tried, once again, to reproduce the issue here: https://gist.github.com/JensRantil/5670869 Unfortunately, I couldn't. I'm closing this issue. Reopen, if anyone has additional information.

@JensRantil
Copy link
Contributor Author

I inlining /partials/desktopimitation/voicemail.jsp in my HTML file was a successful workaround.

I should also be mentioned that inlining voicemail.jsp as <script type="text/ng-template" ...> did not work either.

@arisbartee
Copy link

I had the exact same issue. Using the the "debugger;" statement, I looked at the call stack. I noticed calls into the JQuery library. I removed JQuery and it worked fine.

@JensRantil
Copy link
Contributor Author

I noticed calls into the JQuery library. I removed JQuery and it worked fine.

Interesting. Out of curiousity, what jQuery version were you using? I'll post what version we are using tomorrow when I'm at work.

@arisbartee
Copy link

I was using JQuery 1.8 it was the default with middleman

@JensRantil
Copy link
Contributor Author

I was using jQuery 1.7.2 and jQuery UI 1.8.11 (custom).

@apolishch
Copy link
Contributor

Unfortunately taking jquery out entirely is not an option for me. I've temporarily resolved this by monkey patching the watch on $locationWatch in angular js from:

if ((!changeCounter || oldUrl != $location.absUrl()) {

to

if ((!changeCounter || oldUrl != $location.absUrl() && ($location.absUrl()+'#')!=oldUrl)) {

Obviously if your right separator is not '#', you will need to change the above line.

If anybody has any insight into how to solve this in a more sustainable manner, I'm all ears

@patorjk
Copy link

patorjk commented Aug 26, 2013

I'm getting the same error with Angular version 1.1.4. I removed jQuery and the problem goes away. I'm using jQuery version 1.9.1.

@Framling
Copy link

@apolishch Your solution doesn't work for me, but it looks like a similar solution to one presented in #3915 does wok.
I added near line 11224 (in function $SnifferProvider()):

jQuery = !!window.jQuery,

to check if jQuery is present. And near line 11256 I changed

history: !!($window.history && $window.history.pushState && !(android < 4)),

into

history: !!($window.history && $window.history.pushState && !(android < 4) && !jQuery),

Of course it means that history API wont be used anymore.

@altundal
Copy link

I have digged into commit history off "location.js". And finally found the commit causes this error. And as a workaround I have rolled it back at my local repository. It works; in case anyone else needs and might be the start point to fix this bug.

a32bc40

@notatestuser
Copy link

Reversing that commit greatly reduced the frequency at which this had been happening with my app - thanks @burakaltundal. However, I'm still experiencing same looping condition in kind of a spontaneous fashion that's difficult to reproduce. In the same way, there's browser freezing and console output referring to a $digest() loop caused by $locationWatch.

@superelement
Copy link

Had same problem. This link had a solution:
http://stackoverflow.com/questions/13853844/angular-js-ie-error-10-digest-iterations-reached-aborting

Basically use
$location.path("/home");
instead on using $window

@altundal
Copy link

@jimdoyle82 you are right but $location.path("/home"); will not fix the problem on some mobile platforms(and maybe some others too) as we have tested. Because of that we switch conditionally between $location.path("/home"); and location.hash

@notatestuser
Copy link

And $location.path() doesn't permit navigating outside of the Angular base path (the given path must begin with '/').

@oilart
Copy link

oilart commented Dec 4, 2013

Faced the same issue when using window.history API with angular routing. in angular v1.2 rc3

@kimwz
Copy link

kimwz commented Dec 16, 2013

Below commit may be the solution If you are faced the same issue when using history api in angular v1.2.x

#5425

@chaudhary
Copy link

I am getting this on the latest version of angularjs also when I use ng-include in my code

@btford
Copy link
Contributor

btford commented Feb 27, 2014

@chaudhary can you make a plunkr or jsfiddle in a new issue demonstrating your problem? Thanks!

@kavuri
Copy link

kavuri commented Apr 18, 2014

I have exactly the same issue listed here. I am using AngularJS 1.2.10. I tried to create a plunkr with a code snippet that I have in my project: http://plnkr.co/edit/1jLBAuwvl8RIDKrVFvjS

but am not able to see any of the text box from the ng-include src. I see the looping problem in chrome

@notatestuser
Copy link

@kavuri is there a chance you are bootstrapping your app twice? both programatically and through use of ng-app, perhaps? upgrading to v1.2.15 will help to catch that if it's potentially the problem.

@Ilya-Valasiuk
Copy link

I have the same issue. My code before fix
ng-include="'partials/account/navbar-login'"
after
ng-include="'/partials/account/navbar-login'"
as we can see i forget "/" before partials. It help me.

@kavuri
Copy link

kavuri commented Apr 20, 2014

@scoolboy true, when I had "/" before the directory, it works. Interestingly, if I have a subdirectory under "/partials", like "/partials/graphs/graph.html", then I get errors. Did you happen to face any such problem?

@Ilya-Valasiuk
Copy link

@kavuri no i dont have any problems with this case.
Try this on your router
app.get('/partials/*', function(req, res) {
res.render('../../public/app/' + req.params);
});

@crucialfelix
Copy link

I also experienced this. Complicated to figure out what happens.

related to adding this:

$rootScope.$on('$routeChangeSuccess', function() {
  var path = $window.location.pathname + '#' + $location.path();
  if(typeof $window.ga !== 'undefined') {
    $window.ga('send', 'pageview', {
      page: path
    });
  }
});

sorry I can't isolate it more. dragons be here.

@dignite
Copy link

dignite commented Nov 10, 2014

Version: 1.2.2
I experienced this issue when having a jQuery click listener that compiled and added angular markup. None of the proposed changes worked for me, and the issue occured even though I wasn't calling $location at all.

I noticed that if I entered the page with a hash sign and clicked the element the hashsign got removed, and vide versa. (http://localhost# <-> http://localhost)

Finally I tracked down the issue which was that the click event bubbled up to $rootElement and triggered a click listener defined in http://ajax.googleapis.com/ajax/libs/angularjs/1.2.2/angular.js line 8928. It is unclear to me what that click listener does. The solution for me was to add event.preventDefault() in my own click listener.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests