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

问题描述 投票:2回答:3

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

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。最干净的方法是什么?

angularjs
3个回答
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;
        }
    }
});

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;
    }
  }
}  

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. 具有已配置/注入的路由过滤逻辑的多个拦截器。

哪种方法最适合您将取决于几个因素,例如:

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

关于单身人士的说明

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

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

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

1 - Single Interceptor

丁香的回答已经为此提供了一个例子,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 - Multiple Interceptors (with their own filtering)

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

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的明显的一对一映射,那么在大批量中这可以更容易维护,但是变得很笨拙。在这里假设,也许它们并不像“第1步”,“第2步”等那么明显。

3 - Multiple Interceptors (config based filtering)

与#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);
        }];
    });

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

© www.soinside.com 2019 - 2024. All rights reserved.