Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular UI-Router - Returning rejected promise in resolve is not stopping state transition

I am trying to assure that a user is authenticated before allowing them to transition to specific states. As I understand it (after review other posts), a state transition should not occur if the state's resolve returns a rejected promise and the '$stateChangeError' event should be raised. However this is not what I am experiencing.

Stepping throught the following code, I can see that the deferred promise is rejected but the state transition still occurs and '$stateChangeError' is not triggered. In my module's config I have the following state:

 .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;
                    });
                }]
            }
        })

In the same module, in the run function I have:

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

What am I missing?

like image 749
Nick Avatar asked Jul 17 '14 20:07

Nick


2 Answers

You're returning the promise in the wrong place. Authenticated needs to be a function that returns a promise but you're just returning the promise in the the .then() function and then authenticated is returning 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;

            }]
        }
like image 94
Evan Hobbs Avatar answered Nov 12 '22 13:11

Evan Hobbs


You dont need to create new deferred since you already get promise from 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'); 
              }
        });

     }]
}
like image 7
Sava Jcript Avatar answered Nov 12 '22 14:11

Sava Jcript