使用$ http拦截器重试失败的请求

时间:2015-09-15 14:34:16

标签: angularjs angular-http-interceptors

我的webapp正在谈论的API有时会超载,如果它无法处理请求,则会发送500内部服务器错误。

我的网络应用程序可以发送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);
        }
    };
});

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

2 个答案:

答案 0 :(得分:18)

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

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

file2.coffee
  

注意:在此示例实现中,拦截器将重试请求,直到您收到状态不是 500 的响应。对此的改进可能是在重试和重试一次之前添加一些超时。

答案 1 :(得分:0)

我也想在我的response块中重试请求,因此结合来自SO的不同帖子的多个答案,我编写了如下的拦截器-

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);
            }
        }
    }]);
}])

积分到@ S.Klechkovski,@ Cameron和https://stackoverflow.com/a/20915196/5729813