web-dev-qa-db-ja.com

$ httpインターセプターを使用して失敗したリクエストを再試行します

私のウェブアプリが話している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);
        }
    };
});

サーバーから500応答コードを取得した後、どうすればリクエストを再送信できますか?

13
Dan

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

注:この実装例では、インターセプターは、5とは異なるステータスの応答を受信するまで要求を再試行します。これを改善するには、再試行する前にタイムアウトを追加して、1回だけ再試行することができます。

18
S.Klechkovski

ステータスコードチェックをもう少し拡張することで、サーバー側のエラーの可能性をチェックできます。このインターセプターは、要求を複数回再試行し、応答コード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);
        }
    };
});
3
Cameron