我确信有一种简单的方法可以做我想做的事情,我只是无法绕过它。如果失败,我怎样才能获得角度的http拦截器来重试请求?我想我必须在请求中建立某种承诺吗?然后在响应中我将不得不检查响应是否是错误,如果是,那么做出承诺吗?怎么做的?我一直试图在这里调整示例:http://docs.angularjs.org/api/ng.$http
我尝试使用拦截器的原因是因为我需要在请求URL中添加令牌和其他一些东西,以及处理xdr的一些事情。
答案 0 :(得分:54)
这是一个$ http拦截器,它(立即)重放超时请求(即响应状态0)。构造这个例子有两个非显而易见的(对我来说)元素:
This answer解决了这两个主题,但涉及的更多,因此我在下面添加了简化版本。
joinApp.factory('httpResponseErrorInterceptor',function($q, $injector) {
return {
'responseError': function(response) {
if (response.status === 0) {
// should retry
var $http = $injector.get('$http');
return $http(response.config);
}
// give up
return $q.reject(response);
}
};
});
joinApp.config(function($httpProvider) {
$httpProvider.interceptors.push('httpResponseErrorInterceptor');
});
在实际实现中,您可能需要更复杂的http响应代码处理,重试次数的限制等。
答案 1 :(得分:9)
为了完整起见,这是mygzi's answer的版本,具有重试延迟:
.factory('httpResponseErrorInterceptor', ['$injector', '$q', '$timeout', function($injector, $q, $timeout) {
return {
'responseError': function(response) {
if (response.status === 0) {
return $timeout(function() {
var $http = $injector.get('$http');
return $http(response.config);
}, 15000);
}
return $q.reject(response);
}
};
}])
.config(function($httpProvider) {
$httpProvider.interceptors.push('httpResponseErrorInterceptor');
});
$timeout
返回一个使用函数参数返回的内容完成的promise,因此我们可以方便地返回$http
中包含的$timeout
调用。
答案 2 :(得分:2)
我为之前写过的应用做了这个。要在函数中重写$ http用法(或者最好在服务中,以便您可以轻松地重用它)。如果请求失败,请再次调用该函数。
然后诀窍是将promise对象与每个请求一起传递。如果您为每个请求创建一个新的承诺,那么它将与您返回给原始调用者的那个匹配,因此一旦请求通过,原始调用者将无法解析其承诺。
所以它是这样的(请注意,defer对象在每次重试时传递):
app.service('HttpService', ['$q', function($q) {
this.makeRequest = _makeRequest;
function _makeRequest(url, data, deffered) {
// We want to keep the same promise for each request, so we don't loose track
if (deferred === undefined) {
deferred = $q.defer();
}
// Now make the request
$http({...}).success(...).error(
function(){
// If some condition
_makeRequest(url, data, deffered);
}
)
// Lastly return the promise
return deferred.promise;
}
}])