AngularJS如何捕获所有$http操作的状态码?

3

我的$http函数可能会返回以下错误:

POST http://foobar.dev/foobar 500 (服务器内部错误)

POST http://foobar.dev/foobar 401 (未授权)

有没有一种方法可以捕捉所有状态码?

$http.post('/foobar', form)
    .success(function(data, status, headers, config) {
        console.info(data);
    })
    .error(function(data, status, headers, config) {
        console.error(data);
        if(status === 401) {
            $scope.setTemplate('show-login');
        }
        if(status === 500) {
            $scope.setTemplate('server-error');
        }
    }
);  

$scope.setTemplate()是控制器内设置视图的一个函数。

但我必须对每个error()函数执行此操作,而且还有很多类似这样的函数,这也不符合DRY代码的要求:P

我想要的是捕获错误并根据返回的状态码执行操作。

提示:我没有使用Angular的$routeProvider()

4个回答

6
您可以使用Angular $http 拦截器来实现此功能,就像@Dalorzo解释的那样:
var myApp = angular.module("myApp", [], ['$httpProvider', function($httpProvider) {

    $httpProvider.interceptors.push(['$rootScope', '$q', function($rootScope, $q) {
        return {
            'responseError': function(response) {
                var status = response.status;
                // Skip for response with code 422 (as asked in the comment)
                if (status != 422) {
                    var routes = {'401': 'show-login', '500': 'server-error'};
                    $rootScope.$broadcast("ajaxError", {template: routes[status]});
                }

                return $q.reject(response);
            }
        };
    }]);
});

然后在您的控制器中接收它:

$scope.$on("ajaxError", function(e, data) {
    $scope.setTemplate(data.template);
});

现在,您不必为每个错误函数输入代码。

这看起来很不错!除了.$on("ajaxError的数据始终是未定义的。 - user1469734
哦,抱歉。是我的错。那个函数的第一个参数是事件。我已经更新了答案,请查看一下。如果不行的话,请告诉我。我会尝试一下的。 - Shashank Agrawal
可以工作了!现在有一个问题;它总是拒绝错误。我有一些422响应,我会以不同的方式处理它们。所以我尝试了这个:'responseError': function(response) { if(response.status == 422) { return response; } // 然后是你的代码,但那不是解决方法。 - user1469734

2
这样的话怎么样:
var routes = {'401':'show-login', '500': 'server-error'}; 
$scope.setTemplate(routes[status]);

其中routes是一个包含你的错误代码和期望路由的字典。


不,不会让代码变得DRY。然后我仍然需要将该行添加到每个错误函数中。 - user1469734
1
请不要仅仅进行负面评价,而是解释一下您对答案的问题,因为我认为这个答案是最符合您需求的。 - Shashank Agrawal
@user1469734,这怎么可能比这更简单呢?如果您知道,请分享一下。 - Dalorzo

1
这正是$http拦截器的用途。在这里查看拦截器部分:$http
基本上,您可以为所有$http请求创建通用功能,在其中处理不同的状态。例如:
// register the interceptor as a service
$provide.factory('myHttpInterceptor', function($q, dependency1, dependency2){
    return {
        response: function(response){
            // do something for particular error codes
            if(response.status === 500){
                // do what you want here
            }
            return response;
        }
    };
});

// add the interceptor to the stack
$httpProvider.interceptors.push('myHttpInterceptor');

0
我最初想说的是为$http服务创建一个装饰器,或者创建一个作为$http服务包装器的服务。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接