我试图找出是否可以使用$http
拦截器在请求发生之前取消请求。
有一个触发请求的按钮,但如果用户双击它,我不希望同一个请求被触发两次。
现在,我意识到有几种方法可以解决这个问题,我们已经有了一个可行的解决方案,我们将$http
包装在一个服务中,该服务跟踪当前待处理的请求,并简单地忽略新的请求。相同的方法,网址和数据。
基本上这是我试图用拦截器做的行为:
factory('httpService', ['$http', function($http) {
var pendingCalls = {};
var createKey = function(url, data, method) {
return method + url + JSON.stringify(data);
};
var send = function(url, data, method) {
var key = createKey(url, data, method);
if (pendingCalls[key]) {
return pendingCalls[key];
}
var promise = $http({
method: method,
url: url,
data: data
});
pendingCalls[key] = promise;
promise.finally(function() {
delete pendingCalls[key];
});
return promise;
};
return {
post: function(url, data) {
return send(url, data, 'POST');
}
}
}])
当我查看$http
拦截器的API时,它似乎不是实现此目的的一种方法。我可以访问config
对象,但这是关于它的。
我是否试图超越拦截器可以在这里使用的界限,还是有办法实现?
答案 0 :(得分:1)
根据$http documentation,您可以从请求拦截器返回自己的配置。
尝试这样的事情:
config(function($httpProvider) {
var cache = {};
$httpProvider.interceptors.push(function() {
return {
response : function(config) {
var key = createKey(config);
var cached = cache[key];
return cached ? cached : cached[key];
}
}
});
}
答案 1 :(得分:0)
很老的问题,但我会给出一个机会来处理这种情况。
如果我理解正确,你会尝试:
1 - 发起请求并注册一些内容以引用它;
2 - 如果发生了另一个请求,则要检索该第一个引用并将请求放入同一端点。
这可能由$http
配置对象中的请求超时处理。在拦截器上,您可以验证它是否在当前请求中注册了一个,如果没有,您可以设置一个,保留对它的引用并在之后处理:
function DropoutInterceptor($injector) {
var $q = $q || $injector.get('$q');
var dropouts = {};
return {
'request': function(config) {
// I'm using the request's URL here to make
// this reference, but this can be bad for
// some situations.
if (dropouts.hasOwnProperty(config.url)) {
// Drop the request
dropouts[config.url].resolve();
}
dropouts[config.url] = $q.defer();
// If the request already have one timeout
// defined, keep it, othwerwise, set up ours.
config.timeout = config.timeout || dropouts[config.url];
return config;
},
'requestError': function(reason) {
delete dropouts[reason.config.url];
return $q.reject(reason);
},
'response': function(response) {
delete dropouts[response.config.url];
return response;
},
'responseError': function(reason) {
delete dropouts[reason.config.url];
return $q.reject(reason);
}
};
}