Angularjs 使用$http侦听器重试失败的请求

Angularjs 使用$http侦听器重试失败的请求,angularjs,angular-http-interceptors,Angularjs,Angular Http Interceptors,我的webapp所使用的API有时会过载,如果无法处理请求,则会发送500个内部服务器错误 我的web应用程序可以发送100多个不同的请求,因此,如果我单独对每个请求执行重试,将花费我数小时的键入时间 我已经在使用$httpProvider拦截器,这里是(简化) 从服务器获取500个响应代码后,如何重新发送请求?Angular提供了对配置对象的引用,该对象被$http服务用于在响应(response.config)中执行请求。这意味着,如果我们可以在拦截器中注入$http服务,我们就可以轻松地重

我的webapp所使用的API有时会过载,如果无法处理请求,则会发送500个内部服务器错误

我的web应用程序可以发送100多个不同的请求,因此,如果我单独对每个请求执行重试,将花费我数小时的键入时间

我已经在使用$httpProvider拦截器,这里是(简化)


从服务器获取500个响应代码后,如何重新发送请求?

Angular提供了对配置对象的引用,该对象被$http服务用于在响应(response.config)中执行请求。这意味着,如果我们可以在拦截器中注入$http服务,我们就可以轻松地重新发送请求。由于循环依赖性,在拦截器中简单地注入$http服务是不可能的,但幸运的是有一个解决方法

这是一个如何实现此类拦截器的示例

$httpProvider.interceptors.push(function ($q, $injector) {
    var incrementalTimeout = 1000;

    function retryRequest (httpConfig) {
        var $timeout = $injector.get('$timeout');
        var thisTimeout = incrementalTimeout;
        incrementalTimeout *= 2;
        return $timeout(function() {
            var $http = $injector.get('$http');
            return $http(httpConfig);
        }, thisTimeout);
    };

    return {
        responseError: function (response) {
            if (response.status === 500) {
                if (incrementalTimeout < 5000) {
                    return retryRequest(response.config);
                }
                else {
                    alert('The remote server seems to be busy at the moment. Please try again in 5 minutes');
                }
            }
            else {
                incrementalTimeout = 1000;
            }
            return $q.reject(response);
        }
    };
});
$httpProvider.interceptors.push(函数($q,$injector){
var incrementalTimeout=1000;
函数retryRequest(httpConfig){
var$timeout=$injector.get(“$timeout”);
var thisTimeout=递增的Altimeout;
incrementalTimeout*=2;
返回$timeout(函数(){
var$http=$injector.get('$http');
返回$http(httpConfig);
},超时);
};
返回{
responseError:函数(响应){
如果(response.status==500){
如果(增量输出<5000){
返回retryRequest(response.config);
}
否则{
警报(“远程服务器目前似乎正忙。请在5分钟后重试”);
}
}
否则{
递增时间=1000;
}
返回$q.reject(响应);
}
};
});
注意:在这个示例实现中,拦截器将重试请求,直到您收到状态不同于500的响应。对此的改进可以是在重试之前添加一些超时,并且只重试一次


您可以通过进一步展开状态代码检查来检查任何可能的服务器端错误。此拦截器将尝试重试请求多次,并将在任何响应代码为500或更高的情况下重试。它将在重试前等待1秒,并在尝试3次后放弃

$httpProvider.interceptors.push(function ($q, $injector) {

    var retries = 0,
        waitBetweenErrors = 1000,
        maxRetries = 3;

    function onResponseError(httpConfig) {
        var $http = $injector.get('$http');
        setTimeout(function () {
            return $http(httpConfig);
        }, waitBetweenErrors);
    }

    return {
        responseError: function (response) {
            if (response.status >= 500 && retries < maxRetries) {
                retries++;
                return onResponseError(response.config);
            }
            retries = 0;
            return $q.reject(response);
        }
    };
});
$httpProvider.interceptors.push(函数($q,$injector){
var重试次数=0,
WaitBetweeErrors=1000,
最大重试次数=3次;
函数onResponseError(httpConfig){
var$http=$injector.get('$http');
setTimeout(函数(){
返回$http(httpConfig);
},服务员和中间人);
}
返回{
responseError:函数(响应){
如果(response.status>=500&&retries
我还想在我的
响应
块中重试请求,因此结合来自不同帖子的多个答案,我编写了我的拦截器,如下所示-

app.config(['$httpProvider', function ($httpProvider) {
    $httpProvider.interceptors.push(['$rootScope', '$cookies', '$q', '$injector', function ($rootScope, $cookies, $q, $injector) {
        var retries = 0, maxRetries = 3;

        return {
            request: function (config) {
                var csrf = $cookies.get("CSRF-Token");
                config.headers['X-CSRF-Token'] = csrf;
                if (config.data) config.data['CSRF-Token'] = csrf;
                return config;
            },
            response: function (r) {
                if (r.data.rCode == "000") {
                    $rootScope.serviceError = true;
                    if (retries < maxRetries) {
                        retries++;
                        var $http = $injector.get('$http');
                        return $http(r.config);
                    } else {
                        console.log('The remote server seems to be busy at the moment. Please try again in 5 minutes');
                    }
                }
                return r;
            },
            responseError: function (r) {
                if (r.status === 500) {
                    if (retries < maxRetries) {
                        retries++;
                        var $http = $injector.get('$http');
                        return $http(r.config);
                    } else {
                        console.log('The remote server seems to be busy at the moment. Please try again in 5 minutes');
                    }
                }

                retries = 0;
                return $q.reject(r);
            }
        }
    }]);
}])
app.config(['$httpProvider',函数($httpProvider){
$httpProvider.interceptors.push(['$rootScope','$cookies','$q','$injector',函数($rootScope,$cookies,$q,$injector){
var retries=0,maxRetries=3;
返回{
请求:函数(配置){
var csrf=$cookies.get(“csrf令牌”);
config.headers['X-CSRF-Token']=CSRF;
如果(config.data)config.data['CSRF-Token']=CSRF;
返回配置;
},
答复:功能(r){
如果(r.data.rCode==“000”){
$rootScope.servicererror=true;
如果(重试次数<最大重试次数){
重试++;
var$http=$injector.get('$http');
返回$http(r.config);
}否则{
console.log('远程服务器目前似乎很忙,请在5分钟后重试');
}
}
返回r;
},
响应者:函数(r){
如果(r.状态===500){
如果(重试次数<最大重试次数){
重试++;
var$http=$injector.get('$http');
返回$http(r.config);
}否则{
console.log('远程服务器目前似乎很忙,请在5分钟后重试');
}
}
重试次数=0;
返回$q.reject(r);
}
}
}]);
}])
归功于@S.Klechkovski、@Cameron&


也可以处理丢失的internet连接(HTTP 0状态)。你想让我把它添加到答案中吗?如果你对答案不满意,你能告诉我们如何帮助你解决问题吗?如果在答案的帮助下已经解决了问题,那么最好妥善处理悬赏,或者如果你自己解决了问题,那么最好提供你的解决方案。谢谢。你能提供更多关于失败原因的信息吗?请求失败的原因是服务器过载。如果队列太大或内存不足,服务器将返回504响应。因此,您应该在服务器端解决此问题。如果由于某些原因而无法执行此操作,则最好在重试之前添加超时,并希望在下一次请求时服务器可用。这与我们对$http服务所做的相同。var$timeout=$injector.get(“$timeout”);非常有用!在我的例子中,我使用
response.status===-1
检查取消/超时的请求(请参阅)我
app.config(['$httpProvider', function ($httpProvider) {
    $httpProvider.interceptors.push(['$rootScope', '$cookies', '$q', '$injector', function ($rootScope, $cookies, $q, $injector) {
        var retries = 0, maxRetries = 3;

        return {
            request: function (config) {
                var csrf = $cookies.get("CSRF-Token");
                config.headers['X-CSRF-Token'] = csrf;
                if (config.data) config.data['CSRF-Token'] = csrf;
                return config;
            },
            response: function (r) {
                if (r.data.rCode == "000") {
                    $rootScope.serviceError = true;
                    if (retries < maxRetries) {
                        retries++;
                        var $http = $injector.get('$http');
                        return $http(r.config);
                    } else {
                        console.log('The remote server seems to be busy at the moment. Please try again in 5 minutes');
                    }
                }
                return r;
            },
            responseError: function (r) {
                if (r.status === 500) {
                    if (retries < maxRetries) {
                        retries++;
                        var $http = $injector.get('$http');
                        return $http(r.config);
                    } else {
                        console.log('The remote server seems to be busy at the moment. Please try again in 5 minutes');
                    }
                }

                retries = 0;
                return $q.reject(r);
            }
        }
    }]);
}])