title: Why does AngularJS with ui-router keep firing the $stateChangeStart event?
body: <p>I'm trying to block all ui-router state changes until I've authenticated the user:</p>
  
  <pre><code>$rootScope.$on('$stateChangeStart', function (event, next, toParams) {
    if (!authenticated) {
      event.preventDefault()
      //following $timeout is emulating a backend $http.get('/auth/') request
      $timeout(function() {
        authenticated = true
        $state.go(next,toParams)
      },1000)
    }
  })
  </code></pre>
  
  <p>I reject all state changes until the user has been authenticated, but if I go to an invalid URL that uses the <code>otherwise()</code> configuration, I get an infinite loop with a message:</p>
  
  <pre><code>Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
  Watchers fired in the last 5 iterations: [["fn: $locationWatch; newVal: 7; oldVal: 6"],["fn: $locationWatch; newVal: 8; oldVal: 7"],["fn: $locationWatch; newVal: 9; oldVal: 8"],["fn: $locationWatch; newVal: 10; oldVal: 9"],["fn: $locationWatch; newVal: 11; oldVal: 10"]]
  </code></pre>
  
  <p>Below is my <a href="http://sscce.org/" rel="noreferrer">SSCCE</a>.  Serve it up with <code>python -m SimpleHTTPServer 7070</code> and go to <code>localhost:7070/test.html#/bar</code> to see it explode in your face.  Whereas directly navigating to the only valid angularjs location does not blow up <code>localhost:7070/test.html#/foo</code>:</p>
  
  <pre><code>&lt;!doctype html&gt;
    &lt;head&gt;
      &lt;script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.js"&gt;&lt;/script&gt;
      &lt;script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.js"&gt;&lt;/script&gt;
      &lt;script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.10/angular-ui-router.min.js"&gt;&lt;/script&gt;
    &lt;/head&gt;
    &lt;body ng-app="clientApp"&gt;
      &lt;div ui-view="" &gt;&lt;/div&gt;
  
      &lt;script&gt;
        var app = angular.module('clientApp', ['ui.router'])
  
        var myRouteProvider = [
                  '$stateProvider', '$urlRouterProvider',
          function($stateProvider,   $urlRouterProvider) { 
            $urlRouterProvider.otherwise('/foo');
            $stateProvider.state('/foo', {
              url: '/foo',
              template: '&lt;div&gt;In Foo now&lt;/div&gt;',
              reloadOnSearch: false
            })
          }]
        app.config(myRouteProvider)
  
        var authenticated = false
        app.run([
                   '$rootScope', '$log','$state','$timeout',
          function ($rootScope,   $log,  $state,  $timeout) {
            $rootScope.$on('$stateChangeStart', function (event, next, toParams) {
              if (!authenticated) {
                event.preventDefault()
                //following $timeout is emulating a backend $http.get('/auth/') request
                $timeout(function() {
                  authenticated = true
                  $state.go(next,toParams)
                },1000)
              }
            })
          }
        ])
      &lt;/script&gt;
    &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>Is there an alternative method I should use to accomplish this authentication blocking?  I do realize this authentication blocking is client side only.  I'm not showing the server side of things in this example.</p>