使用$ http拦截器重试失败的请求 [英] Retry failed requests with $http interceptor

查看:80
本文介绍了使用$ http拦截器重试失败的请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的Web应用正在与之交谈的API有时过载,如果无法处理请求,则会发送500 Internal Server Error.

The API my webapp is talking to sometimes overloads and is sending 500 Internal Server Error if it cannot handle request.

我的Web应用程序可以发送100多个不同的请求,因此,如果我分别对每个请求实施重试,则需要花费数小时的输入时间.

There are 100+ different requests my web application can send, so if I implement retry on each individually, it will cost me hours of typing.

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

I'm already using $httpProvider interceptor, here it is (simplified)

$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个响应代码后,如何重新发送请求?

How could I resend a request after getting 500 response code from the server?

推荐答案

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

Angular provides reference to the config object which was used by $http service for doing the request in the response (response.config). That means if we can inject $http service in the interceptor we can easily resend the request. Simple injecting of $http service in the interceptor is not possible because of the circular dependency but luckily there is a workaround for that.

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

This is an example how the implementation of a such interceptor can be done.

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

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

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.

这篇关于使用$ http拦截器重试失败的请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆