2015-11-09 99 views
4

我有一个基于组件的Angular应用程序,其中各个组件加载它们各自的数据。发生错误时,我通常希望组件显示错误消息。

但是,在某些情况下,我希望组件忽略错误并将其留给一些全局错误处理机制来捕获它。

拦截:

angular.module("...").factory("httpInterceptor", function($q) { 
    return { 
     responseError: function(response) { 
      // (1) 
      return $q.reject("I AM CALLED FIRST") 
     } 
}) 

Serivce:

angular.module("...").service("myService", function($http){ 
    return { 
     fetchData: function(){ 
      return $http.get("...")  
     } 
    } 
}) 

控制器:

angular.module("...").controller("MyController", function(myService){ 
    myService.fetchData() 
     .then(function(){ ... }) 
     .catch(function() { 
      // (2) 
      //I AM CALLED LAST 
     }) 
}) 

在大多数情况下,我想在控制器(处理在点的误差(2) )。如果控制器决定忽略该错误(省略该错误),那么该错误仍然可以在拦截器中被捕获。

问题在于拦截器不知道控制器是否意图捕获错误,因为它在控制器之前被调用。因此,拦截器不知道它是否应该显示错误(我不希望全局和本地错误消息)。

如何捕获控制器忽略的http错误?

+0

以另一种方式提出问题:您如何知道是否没有人处理(捕获)承诺链中的错误? – Johannes

回答

7

由于承诺不知道派生承诺的事情,似乎没有办法让它美丽的$ HTTP,拦截器和承诺。

但这里的丑陋的方式,如果你需要一个:在.catch()

$httpProvider.interceptors.push(['$q', '$timeout', 
     function ($q, $timeout) { 
      return { 
       responseError: function (response) { 
        $timeout(function() { 
         if (response.errorHandled) { 
          return; 
         } 
         // global AJAX error handling 
        }, 0); 
        return $q.reject(response); 
       } 
      }; 
     } 
    ]); 

然后某处:

.catch(function(response){response.errorHandled = true;}) 

(我想我看到了一个这样的答案对SO之前,但我不能没有找到它。)

+0

谢谢你,德米特里。事实上,在你提出相同的解决方案之前,我最终解决了这个问题。我同意这不是很好,但它工作正常。我也许应该把这个作为对我自己问题的回答。对不起,关于这个:-) –

+0

这个解决方案的唯一问题是,你总是必须提供这个'catch'表达式,否则,异常将不会被处理,并最终出现控制台中的错误( –

+0

@AnanaKastsiukavets Uncaught exception (或者在这种情况下承诺拒绝)将最终在全局异常处理程序中完成,大多数人以它记录错误并重定向到错误页面的方式实现它。如果您希望继续未定义的行为,也可以通过没有实现全局错误处理程序。 – Dmitry

0

如果你不想在控制器中处理,你可以抛出错误并让$ exceptionHandler来处理它。 您可以创建在配置阶段的一般错误处理程序:

$provide.decorator('$exceptionHandler', extendExceptionHandler); 
0

这是一个有点哈克但有一种方式来增加一个全球性的回退错误处理程序$ HTTP失败和不指定errorCallback请求。

基本上,您装饰$ http服务,以便在$ http请求失败且未指定errorCallback时触发'unhandledHttpError'事件。


这将触发 'unhandledHttpError' 事件:

$http.get('/invalid/url').then(function() { 
    //success handler 
}); 

这将不发射 'unhandledHttpError' 事件:

$http.get('/invalid/url').then(function() { 
    //success handler 
}, function() { 
    //error handler 
}); 

为了处理 'unhandledHttpError' 事件:

$rootScope.$on('unhandledHttpError', function(event, response) {...}); 

这里是一个工作示例:https://jsfiddle.net/45w6o79p/27/

看到小提琴为$ HTTP装修代码,您需要粘贴到您的应用程序添加“unhandledHttpError”事件“的myconfig”方法。