Max
Max

Reputation: 137

Wait for response in AngularJS $http

Okay, so I'm pretty sure I've found the answer multiple times - I just don't understand it.

I'm building a single page application which on each $routeChangeStart checks if the user is logged in. If the user isn't log in, redirect to login page. My issue is that configService.isLoggedIn() is using $http, meaning it's asynchronous and the rest of the code won't wait for it to be resolved.

So the question in short: I need the isLoggedIn() function to be resolved before continuing with any other code.

I've seen a lot on $q.defer() but I can't wrap my head around it.

Thanks in advance.

app.service('configService', ['$http', '$q', '$location', '$rootScope', function ($http, $q, $location, $rootScope) {
    var self = this;

    this.isLoggedIn = function () {
        $http.get('/internalAPI.php?fn=login').then(function (result) {
            if (result.data.isLoggedIn === true) {
                $rootScope.isLoggedIn = true;
            }
            else {
                $rootScope.isLoggedIn = false;
            }
        }, function() {
            $rootScope.isLoggedIn = false;
        });
        return $rootScope.isLoggedIn;
    }
}]);

app.service('navigationService', ['$rootScope', '$location', '$timeout', 'configService', function ($rootScope, $location, $timeout, configService) {

    var self = this;

    $rootScope.$on('$routeChangeStart', function (event, next, current) {
        if (configService.isLoggedIn() !== true) {
            // no logged in user, redirect to /login
            if (next.templateUrl != "resources/views/login.php") {
                $location.path("/login");
                $rootScope.subTitle = 'Login';
            }
        //user is logged in but is trying to view the login page, redirect
        } else if (next.templateUrl == 'resources/views/login.php') {
            $location.path('/');
        }

Upvotes: 0

Views: 1145

Answers (2)

Max
Max

Reputation: 137

Many thanks for that. Went for the approach Rene M. mentioned regarding building an interceptor and let the server-side scripts handle the authentication.

Definitely does the trick, if the 403 status is returned then redirect the user to the login page and update the isLoggedIn variable. Refactoring the code to remove use of the rootScope, was a dirty workaround until I got a hang of the whole angular way of authentication.

Attached a simple example below in case anyone would stumble upon this in the future.

app.config(['$routeProvider', '$locationProvider', '$httpProvider', function ($routeProvider, $locationProvider, $httpProvider) {
    $httpProvider.interceptors.push('responseObserver');

app.factory('responseObserver', ['$location', '$q', function ($location, $q) {
    return {
        'responseError': function (errorResponse) {
            switch (errorResponse.status) {
            case 403:
                //Place logic here
                break;
            case 500:
                //Place logic here
                break;
            }
            return $q.reject(errorResponse);
        }
    };
}]);

Upvotes: 0

suvroc
suvroc

Reputation: 3062

You can just return promise from your function and operate on this promise object. According to Angular $http documentation the $http object is based on promise mechanism

app.service('configService', ['$http', function ($http) {
    var self = this;

    this.isLoggedIn = function () {
        return $http.get('/internalAPI.php?fn=login');
    }
}]);

app.service('navigationService', ['$rootScope', '$location', '$timeout', 'configService', function ($rootScope, $location, $timeout, configService) {

    var self = this;

    $rootScope.$on('$routeChangeStart', function (event, next, current) {
        configService.isLoggedIn().then(function(result) {
            if (result !== true) {
                // no logged in user, redirect to /login
                if (next.templateUrl != "resources/views/login.php") {
                    $location.path("/login");
                    $rootScope.subTitle = 'Login';
                }
            //user is logged in but is trying to view the login page, redirect
            } else if (next.templateUrl == 'resources/views/login.php') {
                $location.path('/');
            }
        }
    }
}

Upvotes: 1

Related Questions