我的webapp正在谈论的API有时会重载,如果无法处理请求,则会发送500内部服务器错误.
我的Web应用程序可以发送100个不同的请求,所以如果我每个单独执行重试,这将花费我几个小时的打字.
我已经在使用$httpProvider拦截器了,这里是(简化的)
- $httpProvider.interceptors.push(function ($q) {
- return {
- responseError: function (response) {
- switch (response.status) {
- case 401 :
- window.location = "/";
- alert('Session has expired. Redirecting to login page');
- break;
- case 500 :
- // TODO: retry the request
- break;
- }
- return $q.reject(response);
- }
- };
- });
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);
- }
- };
- });
Note: In this example implementation the interceptor will retry the request until you receive a response with status that is different than 500. Improvement to this can be adding some timeout before retrying and retrying only once.