Robben_Ford_Fan_boy Robben_Ford_Fan_boy - 1 month ago 9
AngularJS Question

Correct method to Redirect from $http.post in angularjs

Can you tell me what is the correct way to redirect to another page if $http.post returns a specific error code.

Just to add context, I want to redirect to another page if the user is not logged in or authorized to use the API.

function getData(filter) {
var deferred = $q.defer();
var data = JSON.stringify(filter);

$http.post('/myapp/api/getData', data)
.success(function (data, status, headers, config) {
deferred.resolve(data);
})
.error(function (error) {
deferred.reject(error);
});

return deferred.promise;
}

gyc gyc
Answer

The $http.post is misguiding. So far the best answer is @Kliment's. Interceptors are the best way to manage what comes before and after http requests.

However, if your end goal is to prevent access to a page, you have to at least use a routing plugin (ngRoute, ui-router) because with the promise idea there will always be a delay between the http request and the response.

Depending on server response time you'll still see the page display for about a second or so.

With ui-router you simply configure a resolve method for each state you want to protect. It could look like this:

.state('protected',
{
    url : '/protected_page',
    templateUrl : 'secret.html',
    resolve: {
        loggedin: loggedin
    }
})

loggedin refers to a function you define that contains your $http.post call (or better yet a service)

function loggedin($timeout, $q, $location, loginService) {
    loginService.then(function(data) {
        if(data.status == 401) {
            //$timeout(function() { $location.path('/login'); });
            return $q.reject();
        } else {
            return $q.when();
        }
    });
}

Here this particular service returns a 401 status but you can return anything.

The state will not be resolved (and the page not displayed) until it's accepted or rejected.

You can redirect directly from there if you want, although it's not very elegant. ui-router gives you another option with default redirection:

if (tokenIsValid()) 
    $urlRouterProvider.otherwise("/home");
else
    $urlRouterProvider.otherwise("/login");

With otherwise you tell ui-router to go to certain urls if no state exists for a particular request or if a resolve has been rejected.

On another subject, your http request is badly written.

.success and .error are deprecated and you don't need to create a promise ($q) over an $http request that itself already returns a promise.

You have a good example in the documentation linked above.