AngularJS change URL in module.config

2019-04-11 23:18发布

问题:

I use Restangular in my angularjs App & use setErrorInterceptor to handle response error in one place. I want to redirect user to login page if an error occured. I know that the only providers & constants are injectable in configuration phase.

var app = angular.module('ourstandApp', ['ngRoute', 'restangular', 'ui.bootstrap', 'ngCookies', 'angularFileUpload']);
    // Global configuration

    app.config(function (RestangularProvider, baseRequestConfig, $routeProvider, urlsProvider) {
        var getBaseRequestUrl = function () {
            return baseRequestConfig.protocol + "://" + baseRequestConfig.hostName + ":" + baseRequestConfig.portNumber + baseRequestConfig.resourcePath;
    }
        var initializeRoute = function () {
            $routeProvider.when('/', {
                controller: LoginController,
                templateUrl: 'views/login.html'
            }).
            otherwise({
                redirectTo: '/'
            });
        }

        initializeRoute();
        RestangularProvider.setBaseUrl(getBaseRequestUrl());
        RestangularProvider.setErrorInterceptor(function (resp) {
            goToLogin();  //  i want to change url to login page
            return false;
        });
    });

回答1:

the correct way for handling this problem is configuring restangular in run method of angularjs

app.run(Restangular , $location){
    Restangular.setErrorInterceptor(function (resp) {
        $location.path('/login');
        return false;
    });
}


回答2:

Inject $injector to the config block and invite $location when needed:

RestangularProvider.setErrorInterceptor(function (resp) {
   var $location = $injector.get('$location');
   $location.path('/login');
   return false;
});

Also check my other answers:

  • inject $route into a http interceptor
  • Is there a way to request $http for an interceptor?


回答3:

The idea here is to be more specific about how resources are requested. In this excerpt from a project i am using the resolve option of routeProvider.when to look up a resource based on path input and injecting the result as ArticleRequest before resolving the route.

If the api calls the route fails and the $routeChangeError event is fired

App.config(['$routeProvider', '$locationProvider', 'TEMPLATE_PATH',
function ($routeProvider, $locationProvider, TEMPLATE_PATH) {

    $routeProvider.
    when('/', {
        templateUrl: TEMPLATE_PATH + 'views/Home.html',
        controller: 'HomeCtrl',
        caseInsensitiveMatch: true
    }).
    when('/:slug/:nocache?', {
        templateUrl: TEMPLATE_PATH + 'views/Article.html',
        controller: 'ArticleCtrl',
        caseInsensitiveMatch: true,
        resolve: {
            ArticleRequest: ['$http', '$route', function ($http, $route) {
                return $http.post('/api/article/GetArticleBySlug',
                    {
                        slug: $route.current.params.slug,
                        nocache: !!$route.current.params.nocache && $route.current.params.nocache == 'preview'
                    });
            }]
        }
    }).
    otherwise({
        redirectTo: '/'
    });

    // configure html5 to get links working on jsfiddle
    $locationProvider.html5Mode(true);   

}]);

Here is a very simple implementation of the $routeChangeError handler

App.run(['$rootScope', '$location', function($rootScope, $location) {

    $rootScope.$on('$routeChangeError', function (e, current, previous, rejection) {

        console.log("ROUTE ERROR:", current, previous, rejection);
        // you might redirect here based on some logic
        $location.path('[YOUR PATH]');

    });

}]);

and here is the controller

ViewControllers.controller('ArticleCtrl', 
['$scope', '$http', '$routeParams', 'ArticleRequest',
function ($scope, $http, $routeParams, ArticleRequest) {

    console.log(ArticleRequest);

}]);

Is something like this usefull in you case with Restangular?



回答4:

If I understand you correctly you want to redirect the user to a login page based on a status code returned to you by the server? Like a 404 or 403?

If that's the case this is how I handle redirects on a 404 and 403 using setErrorInterceptor in one of my apps. This may not be the best way to do this, but It's been working just fine so far for me.

app.config(['RestangularProvider', function (RestangularProvider) {
    RestangularProvider.setErrorInterceptor(function (response) {
        // Redirect the user to the login page if they are not logged in.
        if (response.status == '403' && response.data.detail == 'Authentication credentials were not provided.') {
            var next = window.location.pathname + window.location.hash;

            window.location.href = '/accounts/login/?next=' + next;
        }

        // Redirect the user on a 404.
        if (response.status == '404') {
            // Redirect to a 404 page.
            window.location.href = '/#/';
        }

        return response;
    });
}]);