Angularjs 拦截某些路线最干净的方法是什么?
我正在使用拦截器,它们拦截所有请求,但我有一些不想干扰请求/响应的路由Angularjs 拦截某些路线最干净的方法是什么?,angularjs,Angularjs,我正在使用拦截器,它们拦截所有请求,但我有一些不想干扰请求/响应的路由 app.service('WizardService', ['$http', function($http) { var base_url = '/api'; var service = {}; service.postStep1 = function (){ return $http.post(base_url+'/step-1'); }; service.p
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。最干净的方法是什么?实现一个拦截器,如中所示 如果需要拦截请求,请在
'requests'
回调中检查config.url
并使用类似regex匹配的内容。例如:
// 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;
}
}
}
丁香回答的是好的,但如果有多条路线,则很难根据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;
}]);
现在,注册拦截器(我只是向您展示拦截器的主要逻辑):
首先,
$http
服务及其使用的$httpProvider.interceptors
属性中没有任何内容可以帮助您完成所需的任务
指
.interceptors
是一个平面阵列(第375行):
他们最终只是被推(或取消)到承诺链中,这取决于是请求还是响应
第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种稍微不同的方法可以解决这个问题
- 拦截器数量
- 路由筛选的复杂性(您的示例可能是一个简化的示例)
- 过滤规则独立于拦截器逻辑更改的可能性
$http
在经历一个长的承诺链时无疑会有一些开销,但这并不像最初看起来的那样费力。也就是说,您在评论中提到,您可能会注册多达100个拦截器,我无法评论可能会或可能不会产生的具体性能影响
1-单拦截器
丁香回答已经为这一点提供了一个例子,沙尚克的答案也是如此。大概是这样的:
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一对一映射,则会变得很尴尬。在这里假设,也许它们并不像“第一步”、“第二步”那么明显
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);
}];
});
首先,设置此拦截器需要做更多的工作,但在我看来,如果您拥有的拦截器不止几个,那么它将是最灵活、最容易维护的拦截器。有什么理由支持使用此拦截器而不是使用多个拦截器?首先,谢谢。但是如果我有100条路线,这就没有意义了。如何使用各种拦截器并将它们分配到特定的路由?
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;
}
}
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);
}];
});