2015-11-09 110 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」方法。