拦截某些路线最干净的方法是什么?

时间:2016-05-26 02:18:44

标签: angularjs

我正在使用拦截器,他们拦截所有请求,但我有一些我不想干扰请求/响应的路线

app.service('WizardService', ['$http', function($http) {

    var base_url = '/api';
    var service = {};

    service.postStep1 = function (){

       return $http.post(base_url+'/step-1');

    };

    service.postStep2 = function (data){

       return $http.post(base_url+'/step-2', data);

    };

    service.postStep3 = function (data){

       return $http.post(base_url+'/step-3', data);

    };

    return service;

}]);

对于第1步和第2步,我想使用InteceptorA和第3步我想使用InterceptorB。最干净的方法是什么?

3 个答案:

答案 0 :(得分:3)

Cloves回答的是好的,但如果有多条路线,则很难根据URL分配多个if条件。此外,如果URL更改,您还需要在拦截器中进行修改。

我想最简洁的方法就是配置。让我们从您的服务开始:

app.service('WizardService', ['$http', function($http) {

    var base_url = '/api';
    var service = {};

    service.postStep1 = function (){
       return $http.post(base_url + '/step-3', null, {interceptMe: 'A'});
    };

    service.postStep2 = function (data){
       return $http.post(base_url + '/step-2', null, {interceptMe: 'A'});
    };

    service.postStep3 = function (data){
       return $http.post(base_url + '/step-3', null, {interceptMe: 'B'});
    };

    service.postStep4 = function (data) {
       // no interception
       return $http.post(base_url + '/step-3');
    };

    return service;
}]);

现在,注册拦截器(我只是向你展示拦截器的主要逻辑):

$httpProvider.interceptors.push(['$rootScope', function($rootScope, $q) {
    return {
        'request': function (config) {
            if (config.interceptMe) {
                if (config.interceptMe === 'A') {
                    // do something for interceptor type A
                } else if (config.interceptMe === 'B') {
                    // do for type B
                }
            }

            return config;
        }
    }
});

答案 1 :(得分:0)

实现单个拦截器,如the documentation for the $http service

所示

如果您需要拦截请求,请在'requests'回调中检查config.url并使用类似正则表达式匹配的内容。例如:

// register the interceptor as a service
$provide.factory('myInterceptor', function() {
  return {
    'request': function(config) {
      if (/step-1$/.test(config.url)) doSomething1();
      if (/step-2$/.test(config.url)) doSomething2();
      if (/step-3$/.test(config.url)) doSomething3();
      return config;
    }
  }
}  

答案 2 :(得分:0)

首先,$http服务中没有任何内容及其$httpProvider.interceptors属性的使用,以帮助您完成您正在寻找的内容。

参考v1.5.6 source

.interceptors是一个计划数组(第375行):

var interceptorFactories = this.interceptors = [];

他们最终只是推送(或未撤回)进入承诺链,这取决于它是否是请求或响应。​​

第986行:

// apply interceptors
forEach(reversedInterceptors, function(interceptor) {
    if (interceptor.request || interceptor.requestError) {
      chain.unshift(interceptor.request, interceptor.requestError);
    }
    if (interceptor.response || interceptor.responseError) {
      chain.push(interceptor.response, interceptor.responseError);
    }
});

所以,除了滚动你自己的$http服务替代品(不是我在这种情况下推荐的东西)之外,你必须在你能做的范围内工作。一个http拦截器本身。换句话说,拦截器(或拦截器)必须自己管理过滤路由。

我看到了3种不同的方式。

  1. 作为“元帅”的单一拦截器。根据路线调用逻辑。
  2. 多个拦截器,每个拦截器都有自己的路由过滤逻辑。
  3. 具有已配置/注入的路由过滤逻辑的多个拦截器。
  4. 哪种方法最适合您将取决于几个因素,例如:

    • 拦截器数量
    • 路由过滤的复杂性(您的示例可以是简化的)
    • 过滤规则将独立于拦截器逻辑而改变的可能性

    关于单身人士的说明

    请记住,服务是单身人士。他们创建了一次,并重新使用。每Angular doco

      

    依赖于服务的每个组件都会获得对服务工厂生成的单个实例的引用。

    所以,虽然如果你已经注册了多个拦截器,$http经历了一个长期的承诺链,毫无疑问会有一些开销,但它并不像它看起来那样费力。 。也就是说,您在评论中提到您可能正在注册多达100个拦截器,我无法评论可能会或可能没有的具体性能影响。

    1 - 单拦截器

    Cloves的答案已经为此提供了一个例子,Shashank也是如此。像这样:

    function SingleInterceptor() {
        var service = {
            request: request
        };
    
        return service;
    
        function request(config) {
            if (config.url === base_url + '/step-1') {
                step1Logic();
            }
            if (config.url === base_url + '/step-2') {
                step2Logic();
            }
            // etc...
            return config;
        }
    }
    

    如果您没有很多不同的拦截器逻辑可以处理,这很简单,但是如果维持更高的音量可能会变得有点笨拙。

    2 - 多个拦截器(有自己的过滤)

    每个拦截器都有自己的逻辑来确定路由是否适用。像:

    function InterceptorStep1() {
        var service = {
            request: request
        };
    
        return service;
    
        function request(config) {
            if (config.url === base_url + '/step-1') {
                // Step 1 logic here
            }
            return config;
        }
    }
    
    function InterceptorStep1() {
        var service = {
            request: request
        };
    
        return service;
    
        function request(config) {
            if (config.url === base_url + '/step-2') {
                // Step 2 logic here
            }
            return config;
        }
    }
    

    如果您想要开始更改过滤规则,或者拦截器与URL没有明显的一对一映射,那么在大批量中这可以更容易维护,但会变得很笨拙。在这里假设,也许他们并不像#34;步骤1","步骤2"等等那么明显。

    3 - 多个拦截器(基于配置的过滤)

    与#2类似,但通过为每个拦截器使用提供程序将路由过滤逻辑与拦截器本身分开。

    function InterceptorB(filterUrl) {
        var service = {
            request: request
        };
    
        return service;
    
        function request(config) {
            if (!filterUrl || filterUrl(config.url)) {
                // Logic here
            }
            return config;
        }
    }
    
    angular
        .module('app')
        .provider('InterceptorB', function InterceptorBProvider() {
            var filterUrlInner;
    
            this.setFilterUrlCallback = function (fn) {
                filterUrlInner = fn;
            };
    
            this.$get = [function InterceptorBFactory($log) {
                return new InterceptorB(filterUrlInner);
            }];
        });
    

    首先要完成这一项工作还有更多工作要做,但在我看来,一旦你拥有的只是一些拦截器,它就会变得最灵活,最容易维护。