Angular UI-Router - возврат отклоненного обещания в решении не останавливает переход состояния

Я пытаюсь заверить, что пользователь аутентифицирован, прежде чем позволить им перейти на определенные состояния. Насколько я понимаю (после просмотра других сообщений), переход состояния не должен происходить, если разрешение состояния возвращает отклоненное обещание и событие $stateChangeError должно быть поднято. Однако это не то, что я испытываю.

Выполняя следующий код, я вижу, что отложенное обещание отклонено, но переход состояния все еще происходит, и '$ stateChangeError' не запускается. В моей конфигурации модуля у меня следующее состояние:

 .state('accounts', {
            url: '/Accounts',
            controller: 'AccountsController',
            templateUrl: 'Scripts/angular/accounts/templates/accounts.tpl.html',
            resolve: {
                authenticated: ['$q', 'AccountService', function ($q, accountService) {
                    var deferred = $q.defer();
                    accountService.userLoggedIn().then(function (loggedIn) {
                        if (loggedIn) {
                            deferred.resolve();
                        } else {
                            deferred.reject('Not logged in'); <-- This happens
                        }
                        return deferred.promise;
                    });
                }]
            }
        })

В том же модуле в функции запуска есть:

 $rootScope.$on('$stateChangeError',
    function (event, toState, toParams, fromState, fromParams, error) {
        $log.debug(error); <-- This is never called
        $state.go('login');
    });

Что мне не хватает?

Ответ 1

Вы возвращаете обещание не в том месте. Аутентифицированная должна быть функцией, которая возвращает обещание, но вы просто возвращаете обещание в функции .then(), а затем аутентифицируется, возвращая undefined:

        resolve: {
            authenticated: ['$q', 'AccountService', function ($q, accountService) {
                var deferred = $q.defer();
                accountService.userLoggedIn().then(function (loggedIn) {
                    if (loggedIn) {
                        deferred.resolve();
                    } else {
                        deferred.reject('Not logged in'); <-- This happens
                    }
                });

                return deferred.promise;

            }]
        }

Ответ 2

Вам не нужно создавать новые отложенные, поскольку вы уже получаете обещание от userLoggedIn():

resolve: {
    authenticated: ['$q', 'AccountService', function ($q, accountService) {

        return accountService.userLoggedIn().then(function (loggedIn) {
              if (loggedIn) {
                   return loggedIn;
              } else {
                   return $q.reject('Not logged in'); 
              }
        });

     }]
}