Angular 1.4.1 UI Router 10 итераций $digest(), когда $state.go вызывается в $stateChangeStart

У меня есть состояние, требующее авторизации. Я слушаю событие $stateChangeStart, и если toState.data.protectedи пользователь не авторизован, я звоню e.preventDefault() и $state.go('login').

Когда я открываю приложение по корневому URL-адресу, я автоматически перенаправляюсь в защищенное состояние. Это вызывает 10 циклов $digest, и я оказываюсь в состоянии входа в систему, когда открываю приложение в корневом URL-адресе, и меня автоматически перенаправляют в защищенное состояние.

Uncaught Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!

См. этот plnkr: http://plnkr.co/edit/1voh7m?p=preview

Я успешно использую аналогичный код в другом проекте с angular 1.2.26 без ошибок.

Пример кода angular 1.4.1, ui.router 0.2.15:

//config block
$urlRouterProvider.otherwise('/main');   
$stateProvider
 .state('main', {
   url: '/main',
     templateUrl: 'main.html',
     controller: 'MainController as main',
     data: {'protected': true}
 }) 
 .state('login', {
     url: '/login',
     templateUrl: 'login.html',
     controller: 'LoginController as login'
 });

// in a run block
$rootScope.$on("$stateChangeStart", function (event, toState) {
    if (!event.defaultPrevented && toState.data &&
            toState.data.protected) {
        // the user is not authorized, do not switch to state
        event.preventDefault();
        // go to login page
        $state.go('login');
    }
});

Вы знаете, что вызывает петлю?

Интересно, могут ли вещи происходить следующим образом:

  1. Перехват перехода в состояние main.submain
  2. Начать переход в состояние входа
  3. Маршрутизатор пользовательского интерфейса получает информацию об отмене первого перехода.
  4. Маршрутизатор пользовательского интерфейса запускает $urlRouter.update() и начинает переход на main.submain

EDIT: Упрощенная конфигурация состояния.


person kvetis    schedule 02.07.2015    source источник
comment
Где вы определяете, какие данные защищены?   -  person user3727843    schedule 02.07.2015
comment
Используя определение состояния: data: {'protected': true} в основном состоянии. Состояние прототипически наследуется, поэтому состояние main.submain имеет то же значение.   -  person kvetis    schedule 03.07.2015
comment
Приношу извинения, у меня был неправильный планк, который не продемонстрировал проблему.   -  person kvetis    schedule 03.07.2015
comment
если я не ошибаюсь, вы не должны использовать $urlRouterProvider с одной веткой $urlRouterProvider.otherwise('/main'); , потому что для любого другого URL-адреса он пытается перенаправить на 'main' и вы в бесконечном цикле, у меня есть немного измените свой плункер, попробуйте проверить его: plnkr.co/edit/RyWEusonoBhfQjwD32uu?p=preview   -  person Grundy    schedule 07.07.2015
comment
@Grundy Спасибо. Я только что пришел сюда, чтобы опубликовать ответ на подобное решение. Я считаю, что вы должны иметь возможность использовать $urlRouterProvider.otherwise('/main'); с моим решением, потому что вы просто хотите иметь какое-то перенаправление по умолчанию. Мне нравится ваш план, и я опубликую ответ через минуту.   -  person kvetis    schedule 07.07.2015


Ответы (1)


Это проблема UI.Router — см. эту проблему на Github: https://github.com/angular-ui/ui-router/issues/600

По сути, если вы используете .otherwise('/main') (также указанный @Grundy), тогда URL-адрес изменяется на /main, когда путь не может быть разрешен. После $locationChangeSuccess вызывается мой слушатель, и я отклоняю перенаправление с помощью event.preventDefault(). Это приводит к тому, что местоположение снова меняется на неизвестный путь, что приводит к повторному использованию резервного пути. Это вызывает бесконечный цикл. Решение таково:

$urlRouterProvider.otherwise(function($injector) {
  var $state = $injector.get('$state');
  $state.go('main');
});

Вы можете указать функцию, которая вызывается с помощью $injector, и вы можете перенаправить в свое основное состояние (или 404) без смены местоположения туда и обратно. Спасибо ребятам на Github, я должен был поискать там, прежде чем публиковать этот вопрос.

Рабочий план: http://plnkr.co/edit/eQXaIk

person kvetis    schedule 07.07.2015
comment
Помогло, огромное спасибо! - person Rantiev; 06.06.2017