Подтвердить что ты не робот

Повторить неудачные запросы с помощью перехватчика $http

API my webapp иногда перегружает и отправляет 500 Internal Server Error, если он не может обрабатывать запрос.

Есть 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 кода ответа с сервера?

4b9b3361

Ответ 1

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

Примечание. В этом примере реализации перехватчик будет повторять запрос до тех пор, пока вы не получите ответ со статусом, который отличается от 500. Улучшение этого может заключаться в добавлении некоторого таймаута перед повторной попыткой и повторной попыткой только один раз.

Ответ 2

Вы можете проверить любые возможные ошибки на стороне сервера, расширив код состояния еще немного. Этот перехватчик будет пытаться повторить запрос несколько раз и будет делать это в любом ответном коде 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);
        }
    };
});