2015-11-29 4 views
9

मैं जो एक $http interceptor रूप में लिखा है मेरी कोणीय अनुप्रयोग के लिए एक वैश्विक त्रुटि हैंडलर है, लेकिन मैं इसे एक कदम आगे ले करना चाहते हैं। क्या मैं चाहता हूँ प्रत्येक $http कॉल कि विफल रहता है (अस्वीकार कर दिया है), किसी भी "श्रृंखलित" वादा के उपभोक्ताओं पहले, त्रुटि को हल करने का प्रयास करना चाहिए के लिए है और यदि यह अभी भी अनसुलझे (पकड़े नहीं) है, तो मैं चाहूँगा लेने के लिए वैश्विक त्रुटि हैंडलर।वैश्विक त्रुटि हैंडलर है कि केवल पकड़ता "बिना क्रिया" का वादा किया

उपयोग के मामले में, है मेरी वैश्विक त्रुटि हैंडलर स्क्रीन के शीर्ष पर एक ग्राउल "alert box" को दर्शाता है। लेकिन मेरे पास कुछ मोडल हैं जो पॉप अप करते हैं, और मैं स्पष्ट रूप से त्रुटियों को संभालता हूं, जो मोडल में एक त्रुटि संदेश दिखाता है। इसलिए, अनिवार्य रूप से, इस मोडल नियंत्रक को अस्वीकार किए गए वादे को "संभाला" के रूप में चिह्नित करना चाहिए। लेकिन चूंकि इंटरसेप्टर हमेशा पहले एक $http error पर चलाने के लिए हो रहा है, मैं यह करने के लिए एक तरह से समझ नहीं कर सकते हैं।

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'); 
    }) 

यह मैं कैसे मोडल वादा कॉल की तरह लग रहे करने के लिए उम्मीद थी की किसी न किसी तरह कोड है::

$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

आप सर्वर साइड पर यह बजाय लागू करने के बारे में सोचा है? इसके अलावा जब आप कहते हैं कि इसे * हल करने का प्रयास करना चाहिए, तो क्या आप इसका उदाहरण दे सकते हैं। – Rajesh

+0

सर्वर पर ऐसा नहीं कर सकता है, पूरा बिंदु क्लाइंट पक्ष के वादे के साथ काम करना है। हल करने का प्रयास करके, मेरा मतलब है कि वैश्विक त्रुटि हैंडलर को http वादे में त्रुटियों के लिए अंतिम पकड़ होना चाहिए। वर्तमान में यह त्रुटि पर चलने वाली पहली बात है। –

उत्तर

2

1. समाधान (hacky रास्ता)

यहाँ मेरी इंटरसेप्टर कोड है

आप आप के लिए क्या कर रही है कि एक सेवा बनाने के द्वारा ऐसा कर सकते हैं। क्योंकि वादे श्रृंखला सक्षम हैं और आप मूल रूप से नियंत्रक स्तर पर handled संपत्ति को चिह्नित करते हैं, तो आपको यह वादा अपनी सेवा में पारित करनी चाहिए और यह अनचाहे त्रुटियों का ख्याल रखेगी।

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

2. समाधान (पसंदीदा तरीका)

या बेहतर समाधान $ http के लिए एक आवरण बना सकते हैं और इस तरह से कुछ करने के लिए होगा:

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); 
} 

यहाँ myhttp सेवा कॉल करेंगे दी सफलता लागू करते हैं और विफल कॉलबैक और फिर इसे अपने ही faild कॉलबैक श्रृंखला कर सकते हैं और देखें कि क्या संभाला संपत्ति सही या गलत है।

myhttp सेवा कार्यान्वयन (अद्यतन, setAsHandled समारोह जो सिर्फ वैकल्पिक है जोड़ा है, लेकिन यह एक अच्छा समाधान है, क्योंकि यह एक ही स्थान पर (विशेषता 'संभाला' आसानी से अस्थिर में सब कुछ रहता है और एक ही स्थान पर):

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. समाधान

ही #2 लेकिन कम कोड एक ही प्राप्त करने की आवश्यकता के रूप में:

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); 
} 

हे वहाँ उदाहरण:

//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(){ ... } 

myhttp सेवा कार्यान्वयन:

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

यह काम कर सकता है ...मैं हर जगह '' '$ q''' पर निर्भरता को हटाना चाहता हूं, हालांकि मैं' '' http''' का उपयोग कर रहा हूं ... संभवतः '' 'setAsHandled'' में अस्वीकार करने के लिए पर्याप्त आसान है 'सेवा विधि। –

+0

नहीं, आपको अपने $ q की आवश्यकता होगी, क्योंकि आपको अपने असफल हैंडलर में अपना वादा अस्वीकार करना होगा। अन्यथा आपके 'get' सेवा फ़ंक्शन में यह विफलता केस नहीं पकड़ेगा। – Iamisti

+0

सही है, लेकिन मैं कह रहा हूं कि मैं '' '$ q'''' '' $ q''' को इंजेक्ट नहीं करना चाहता हूं, जिसका उपयोग मैं '' 'http''' –

संबंधित मुद्दे