2015-11-29 22 views
9

Tôi có trình xử lý lỗi toàn cầu cho ứng dụng góc của tôi được viết là $http interceptor, nhưng tôi muốn tiến thêm một bước nữa. Những gì tôi muốn là cho mỗi cuộc gọi $http không thành công (bị từ chối), bất kỳ "chuỗi" người tiêu dùng của lời hứa đầu tiên nên cố gắng giải quyết lỗi, và nếu nó là không được giải quyết (không bị bắt), thì tôi muốn xử lý lỗi toàn cầu để tiếp quản.Trình xử lý lỗi toàn cục chỉ bắt các lời hứa "không được xử lý"

Trường hợp sử dụng là, trình xử lý lỗi toàn cục của tôi hiển thị hình chữ nhật "alert box" ở đầu màn hình. Nhưng tôi có một vài phương thức bật lên và tôi xử lý các lỗi một cách rõ ràng ở đó, hiển thị thông báo lỗi trong chính phương thức đó. Vì vậy, về cơ bản, bộ điều khiển phương thức này nên đánh dấu lời hứa bị từ chối là "xử lý". Nhưng kể từ khi kẻ đánh chặn luôn luôn có vẻ là người đầu tiên chạy trên một $http error, tôi không thể tìm ra một cách để làm điều đó.

Đây là mã đánh chặn của tôi:

angular.module("globalErrors", ['angular-growl', 'ngAnimate']) 
    .factory("myHttpInterceptor", ['$q', '$log', '$location', '$rootScope', 'growl', 'growlMessages', 
     function ($q, $log, $location, $rootScope, growl, growlMessages) { 
      var numLoading = 0; 
      return { 
       request: function (config) { 
        if (config.showLoader !== false) { 
         numLoading++; 
         $rootScope.loading = true; 
        } 
        return config || $q.when(config) 
       }, 
       response: function (response) { 
        if (response.config.showLoader !== false) { 
         numLoading--; 
         $rootScope.loading = numLoading > 0; 
        } 
        if(growlMessages.getAllMessages().length) { // clear messages on next success XHR 
         growlMessages.destroyAllMessages(); 
        } 
        return response || $q.when(response); 
       }, 
       responseError: function (rejection) { 
        //$log.debug("error with status " + rejection.status + " and data: " + rejection.data['message']); 
        numLoading--; 
        $rootScope.loading = numLoading > 0; 
        switch (rejection.status) { 
         case 401: 
          document.location = "/auth/login"; 
          growl.error("You are not logged in!"); 
          break; 
         case 403: 
          growl.error("You don't have the right to do this: " + rejection.data); 
          break; 
         case 0: 
          growl.error("No connection, internet is down?"); 
          break; 
         default: 
          if(!rejection.handled) { 
           if (rejection.data && rejection.data['message']) { 
            var mes = rejection.data['message']; 
            if (rejection.data.errors) { 
             for (var k in rejection.data.errors) { 
              mes += "<br/>" + rejection.data.errors[k]; 
             } 
            } 
            growl.error("" + mes); 
           } else { 
            growl.error("There was an unknown error processing your request"); 
           } 
          } 
          break; 
        } 
        return $q.reject(rejection); 
       } 
      }; 
     }]).config(function ($provide, $httpProvider) { 
     return $httpProvider.interceptors.push('myHttpInterceptor'); 
    }) 

Đây là mã đại khái về cách tôi mong đợi cuộc gọi lời hứa phương thức để trông giống như:

$http.get('/some/url').then(function(c) { 
       $uibModalInstance.close(c); 
      }, function(resp) { 
       if(resp.data.errors) { 
        $scope.errors = resp.data.errors; 
        resp.handled = true; 
        return resp; 
       } 
      }); 
+0

Bạn đã nghĩ đến việc thực hiện nó trên phía máy chủ để thay thế? Ngoài ra khi bạn nói nó nên * cố gắng để giải quyết *, bạn có thể cho một ví dụ về nó. – Rajesh

+0

Không thể làm điều đó trên máy chủ, toàn bộ điểm là làm việc với phía khách hàng hứa hẹn. Bằng cách cố gắng giải quyết, tôi có nghĩa là trình xử lý lỗi toàn cầu phải là phần lưu trữ LAST cho các lỗi trong lời hứa http. Hiện tại nó là thứ đầu tiên chạy trên một lỗi. –

Trả lời

2

1. Giải pháp (cách hacky)

Bạn có thể làm điều đó bằng cách tạo một dịch vụ làm điều đó cho bạn. Bởi vì các lời hứa có thể thực hiện được chuỗi và bạn về cơ bản đánh dấu một thuộc tính là handled ở cấp bộ điều khiển, bạn nên chuyển lời hứa này cho dịch vụ của mình và nó sẽ xử lý các lỗi không được giải quyết.

myService.check(
    $http.get('url/to/the/endpoint') 
      .then(succCallback, errorCallback) 
); 

2. Giải pháp (cách ưa thích)

Hoặc là giải pháp tốt hơn là để tạo ra một wrapper với $ http và làm điều gì đó như thế này:

myhttp.get('url/to/the/endpoint', successCallback, failedCallback); 

function successCallback(){ ... } 
function failedCallback(resp){ 
    //optional solution, you can even say resp.handled = true 
    myhttp.setAsHandled(resp); 

    //do not forget to reject here, otherwise the chained promise will be recognised as a resolved promise. 
    $q.reject(resp); 
} 

đây gọi dịch vụ myhttp sẽ áp dụng thành công đã cho và các cuộc gọi lại không thành công và sau đó nó có thể tự gọi lại chuỗi gọi ngược của mình và kiểm tra xem thuộc tính được xử lý có đúng hay sai.

Việc thực hiện dịch vụ myhttp (cập nhật, bổ sung setAsHandled chức năng mà chỉ là không bắt buộc nhưng đó là một giải pháp đẹp hơn vì nó giữ mọi thứ ở một nơi (thuộc tính 'xử lý' dễ dàng thay đổi và ở một nơi):

function myhttp($http){ 
    var service = this; 

    service.setAsHandled = setAsHandled; 
    service.get = get; 

    function setAsHandled(resp){ 
     resp.handled = true; 
    } 

    function get(url, successHandler, failedHandler){ 
     $http.get(url) 
      .then(successHandler, failedHandler) 
      .then(null, function(resp){ 
        if(resp.handled !== true){ 
         //your awesome popup message triggers here. 
        } 
      }) 
    } 
} 

3. giải pháp

tương tự như #2 nhưng ít mã cần thiết để đạt được như vậy:

myhttp.get('url/to/the/endpoint', successCallback, failedCallback); 

function successCallback(){ ... } 
function failedCallback(resp){ 
    //if you provide a failedCallback, and you still want to have your popup, then you need your reject. 
    $q.reject(resp); 
} 

O ther dụ:

//since you didn't provide failed callback, it'll treat as a non-handled promise, and you'll have your popup. 
myhttp.get('url/to/the/endpoint', successCallback); 

function successCallback(){ ... } 

Dịch vụ myhttp thực hiện:

function myhttp($http){ 
    var service = this; 

    service.get = get; 

    function get(url, successHandler, failedHandler){ 
     $http.get(url) 
      .then(successHandler, failedHandler) 
      .then(null, function(){ 
       //your awesome popup message triggers here. 
      }) 
    } 
} 
+0

Điều này có thể hoạt động ...Tôi muốn loại bỏ sự phụ thuộc vào '' '$ q''' ở khắp mọi nơi mà tôi đang sử dụng' '' $ http''' mặc dù ... có lẽ dễ dàng đủ để chỉ làm việc từ chối trong '' 'setAsHandled'' 'phương thức dịch vụ. –

+0

không, bạn sẽ cần $ q, vì bạn phải từ chối lời hứa trong trình xử lý không thành công của mình. Nếu không, trong hàm 'get' của bạn, nó sẽ không bắt được trường hợp lỗi của nó. – Iamisti

+0

đúng, nhưng tôi nói rằng tôi không muốn tiêm '' '$ q''' vào mọi nơi tôi đang sử dụng' '' $ http''' –

Các vấn đề liên quan