AngularJS的全局Ajax错误处理程序


82

当我的网站是100%jQuery时,我曾经这样做:

$.ajaxSetup({
    global: true,
    error: function(xhr, status, err) {
        if (xhr.status == 401) {
           window.location = "./index.html";
        }
    }
});

为401错误设置全局处理程序。现在,我将angularjs与$resource$http一起使用,以向服务器发送(REST)请求。有什么办法可以类似地用angular设置全局错误处理程序吗?



1
不,我们想为该应用程序执行全局错误401处理程序
cricardol'Aug

大声笑,您是否考虑过想要的内容,但是拥有不同的http状态(可以更改)?无论如何,pkozlowski.opensource的答案向您展示了如何进行
MilkyWayJoe

不,它更像是
贾斯汀

Answers:


97

我还在用角度创建一个网站,并且遇到了相同的全局401处理障碍。当我遇到此博客文章时,我最终使用了HTTP拦截器。也许您会发现它和我一样有用。

“基于AngularJS(或类似)的应用程序中的身份验证。” espeo软件

编辑:最终解决方案

angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives'], function ($routeProvider, $locationProvider, $httpProvider) {

    var interceptor = ['$rootScope', '$q', function (scope, $q) {

        function success(response) {
            return response;
        }

        function error(response) {
            var status = response.status;

            if (status == 401) {
                window.location = "./index.html";
                return;
            }
            // otherwise
            return $q.reject(response);

        }

        return function (promise) {
            return promise.then(success, error);
        }

    }];
    $httpProvider.responseInterceptors.push(interceptor);

4
需要返回$ q.reject(response); 当状态== 401时,避免产生嘈杂的角度误差
s_t_e_v_e 2013年

1
@daniellmb。这取决于。如果您确实要转到另一个页面,而不仅仅是更改视图,那么您实际上应该使用$ window。如果您的登录页面只是角度的另一个视图和控制器,则可以使用$ location.path
uriDium

1
@uriDium对,我的意思是使用提供的角度对象,以便您可以进行模拟和测试。
daniellmb

22
$ httpProvider.responseInterceptors现在已弃用。请参阅docs.angularjs.org/api/ng.$http#description_interceptors
crystalmo 2014年

1
成功后,您需要像return response || $q.when(response);这样返回,以便如果响应为空,则还会返回一个Promise对象。
Ashish Gaur 2015年

77

请注意,Angular 1.1.4不推荐使用responseInterceptor。在下面,您可以找到基于官方文档的摘录,其中显示了实现拦截器的新方法。

$provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
  return {
    'response': function(response) {
      // do something on success
      return response || $q.when(response);
    },

   'responseError': function(rejection) {
      // do something on error
      if (canRecover(rejection)) {
        return responseOrNewPromise;
      }
      return $q.reject(rejection);
    }
  };
});

$httpProvider.interceptors.push('myHttpInterceptor');

这是使用Coffeescript在我的项目中的外观:

angular.module("globalErrors", ['appStateModule']).factory "myHttpInterceptor", ($q, $log, growl) ->
  response: (response) ->
    $log.debug "success with status #{response.status}"
    response || $q.when response

  responseError: (rejection) ->
    $log.debug "error with status #{rejection.status} and data: #{rejection.data['message']}"
    switch rejection.status
      when 403
        growl.addErrorMessage "You don't have the right to do this"
      when 0
        growl.addErrorMessage "No connection, internet is down?"
      else
        growl.addErrorMessage "#{rejection.data['message']}"

    # do something on error
    $q.reject rejection

.config ($provide, $httpProvider) ->
  $httpProvider.interceptors.push('myHttpInterceptor')

但是在responseError拦截器中将没有xhr数据或其他有用的信息。甚至无法决定是否可以恢复。
zw0rk

1
@ zw0rk您将在...内部responseErrorrejection拥有所需的一切。
兰登2014年

最后一行是否$httpProvider...包裹在一个config()块中?
2014年

确实,我已经编辑了答案以显示如何在我的项目中使用Coffeescript做到这一点。如果您更喜欢Javascript,请使用js2coffee.org
MikeR 2014年

函数response下的所有引用responseError实际上rejection都不应该是引用(或者参数应该将其名称更改为response
Adam Nofsinger 2014年

16

创建<script type="text/javascript" src="../js/config/httpInterceptor.js" ></script>具有以下内容的文件:

(function(){
  var httpInterceptor = function ($provide, $httpProvider) {
    $provide.factory('httpInterceptor', function ($q) {
      return {
        response: function (response) {
          return response || $q.when(response);
        },
        responseError: function (rejection) {
          if(rejection.status === 401) {
            // you are not autorized
          }
          return $q.reject(rejection);
        }
      };
    });
    $httpProvider.interceptors.push('httpInterceptor');
  };
  angular.module("myModule").config(httpInterceptor);
}());

@ThilakRaj上面的代码应在每个http请求上运行。因此,请在Chrome中创建两个断点,一个在“ return response”行上,另一个在“ return $ q.reject”行上,以检查其是否可以正常运行。
Jan-TerjeSørensen'2
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.