AngularJS:捕获所有响应状态 500

AngularJS: Catch all response status 500

本文关键字:响应 状态 AngularJS      更新时间:2023-09-26

这似乎是一个奇怪的请求。我想知道是否有办法使用 $http 拦截器来捕获响应状态为 500 的第一个 URL,然后停止所有后续请求和进程并做点什么?

Thomas 的回答是正确的,但此解决方案目前已弃用。你应该做这样的答案。

app.factory('errorInterceptor', function ($q) {
    var preventFurtherRequests = false;
    return {
        request: function (config) {
            if (preventFurtherRequests) {
                return;
            }
            return config || $q.when(config);
        },
        requestError: function(request){
            return $q.reject(request);
        },
        response: function (response) {
            return response || $q.when(response);
        },
        responseError: function (response) {
            if (response && response.status === 401) {
                // log
            }
            if (response && response.status === 500) {
                preventFurtherRequests = true;
            }
            return $q.reject(response);
        }
    };
});
app.config(function ($httpProvider) {
    $httpProvider.interceptors.push('errorInterceptor');    
});

您可以通过$httpProvider.responseInterceptors捕获所有响应。

为此,您必须创建如下工厂:

app.factory('SecurityHttpInterceptor', function($q) {
        return function (promise) {
            return promise.then(function (response) {
                return response;
            },
            function (response) {
                if (response.status === 500) {
                    //DO WHAT YOU WANT
                }
                return $q.reject(response);
            });
        };
    });

在此工厂中,如果响应状态为 500,您将捕获响应状态,做您想做的事。然后拒绝响应。

现在你必须把工厂放在配置模块的$httProvider responseInterceptors中,就像这样:

app.config(function ($routeProvider, $httpProvider) {
    $routeProvider
        .when('/', {
            templateUrl: 'views/home.html',
            controller: 'HomeCtrl'
        })
        .otherwise({
            templateUrl: 'views/404.html'
        });
    $httpProvider.responseInterceptors.push('SecurityHttpInterceptor');
})

你可以创建一个服务和拦截器来处理这个问题,

.factory('ServerErrorService', function() {
        var _hasError = false
        return {
            get hasError() {
                return _hasError;
            },
            set hasError(value) {
                _hasError = value;
                // you could broadcast an event on $rootScope to notify another service that it has to deal with the error
            },
            clear: clear
        }
        function clear() {
            _hasError = false;
        }
})

.factory('ServerErrorInterceptor', function ($q, ServerErrorService) {
    var interceptor = {
        request: function(config) {
            if(ServerErrorService.hasError) {
                var q = $q.defer();
                q.reject('prevented request');
                return q.promise;
            }
            return config;
        },
        responseError: function(response) {
            if(response.status === 500) {
                ServerErrorService.hasError = true;
            }
            return $q.reject(response);
        }
    }
    return interceptor;
})

如果您想允许再次提出请求,则只需调用ServerErrorService.clear()

您可以使用此答案的修改版本。虽然我不确定如何 - 如果您愿意 - 您将取消此操作并允许后续请求。

https://stackoverflow.com/a/25475121/1798234

.factory('ServerErrorInterceptor', function ($q) {
    var canceller = $q.defer();
    var interceptor = {
        request: function(config) {
            config.timeout = canceller.promise;
            return config;
        },
        responseError: function(response) {
            if(response.status === 500) {
                canceller.resolve('server error');
            }
            return $q.reject(response);
        }
    }
    return interceptor;
})

对于这两种解决方案,要记住的一件事是,如果在此之后有任何其他拦截器定义了responseError方法,或者设置了.catch处理$http承诺的任何处理程序,它们将收到一个响应对象,其中包含{data:null, status:0}