Maksym
Maksym

Reputation: 3428

Pause transition and restart after async call

I would like to check if user is logged each time the state I transition to or it's parent has some isLogged data attribute. My code is:

        service.watchHasAccess = function(){
        $rootScope.$on('$stateChangeStart', function(event,toState,toStateParams){
            if(typeof toState.data !=='undefined' && typeof toState.data.loggedIn !== 'undefined' && toState.data.loggedIn == true){
                api.getWithPromise('user/isLoggedIn').then(function(response){
                    if(response.status !=='OK'){
                        event.preventDefault();
                        FlashMessage.showError('Zaloguj się aby przejść tutaj.');
                        $state.go('MainPage');                            
                    }
                });
            }
        });

The problem is that when transitioning to restricted state it does load, but it almost immediately redirects to MainPage state. It is like flash. It is because I use async request so I assume that state just transition no matter what result of request, but then response comes and I am transitioned properly. What I would like to achieve is to wait until promise get resolved then check and eventually redirect user to 'MainPage'. Is that possible ?

Upvotes: 1

Views: 620

Answers (1)

TheSharpieOne
TheSharpieOne

Reputation: 25726

You would need to use promises for your asyc and resolve or reject the promise based on what is returned. I would suggest that the URL switching would take place in the $stateChangeError event listener, which would be fired by rejection of the promise. You can pass the location you want to go to in the reject([data]) to the listener.

http://fiddle.jshell.net/L9jxf/2/

Some promise that will reject after a timeout (simulates server call)

        protected: ['$timeout', '$q', function ($timeout, $q) {
            var deferred = $q.defer();
            $timeout(function () {
                deferred.reject({type:'redirect',location:'401'});
            }, 1000);
            return deferred.promise;
        }]

This handles the rejection

app.run(function ($rootScope, $state) {
    $rootScope.$on('$stateChangeError', function (e, to, toParams, from, fromParams, error) {
        if (error.type === 'redirect') {
            $state.transitionTo(error.location);
        }
    });
});

Upvotes: 1

Related Questions