简体   繁体   中英

Is there a way to prevent the initial state from loading when my angularjs app starts up?

Background

My app needs to make a request to the server to verify whether or not the user has an authenticated session, before the first state is loaded. As depending on on the url, the user may need to be redirected to the login page.

ie if the initial url is myapp.com/#/profile and the user doesn't have a pre-existing authenticated session, they'll be redirected to myapp.com/#/login


Problem

I have logic in place to deal with this situation, but immediately after the session data request is made to the server and before it completes, the initial state change is triggered and the page loads and displays, before the server responds


Possible Solutions

1) I'm using django as my backend, so could just remove the initial server request from the app and pass the data direct to the app in the django template. Either through

  • ng-init of the main controller - although i've read that this is a bad idea, as it's not it's intended usage

  • Or in a script tag in the django template - which i'm loathe to do, as i'd rather keep all my application logic seperate in js files

2) Listen for the initial $stateChangeStart, cancel it and then call $state.reload() once the server requests completed


Question

It would seem to me to be a fairly common requirement to fulfill certain criteria before the initial state change occurs, so i'm wondering if i've missed something in the docs and there's already an inbuilt way to deal with this scenario?

Or is there a way to deactivate the $urlRouterProvider/$stateProvider to prevent the initial state change from occurring?

Assuming that all of your authentication logic is already inside something like AuthService , wouldn't it be possible to do the following?

// 'AuthService' injected earlier
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
    if (!AuthService.isAuthenticated()) {
        // prevent navigation. don't go anywhere;
        // navigation will occur inside AuthService
        event.preventDefault();

        AuthService.setNextState(toState.name);
        AuthService.authenticateWithServer();
    }
    // proceed normally if user is already authenticated
});

Then, your AuthService :

app.service('AuthService', function($rootScope, $http, $state) {
    var next;

    this.setNextState = function(nextState) { next = nextState; };

    this.isAuthenticated = function() { ... };

    this.authenticateWithServer = function() {
        $http.post('/authen', { ... }).success(function(user){
            // house-keeping
            $rootScope.user = user;

            // navigate by state name
            $state.go(next);
        }).error(function(error) {
            // navigate to login screen
            $state.go('login');
        });
    };
});

This way, your state definition is clean, and the authentication logic is isolated in one place. You can also be sure that navigation will never take place until you have all the info you need.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM