2015-08-11 3 views
4

У меня есть перехватчик в данный момент, который обрабатывает мои $ http ошибки. Он немного похож на это:AngularJS httpInterceptors and toastr

.factory('RequestsErrorHandler', ['$q', '$injector', '$rootScope', 'ErrorService', function ($q, $injector, $rootScope, service) { 
    var specificallyHandled = function (specificallyHandledBlock) { 
     specificallyHandleInProgress = true; 

     try { 
      return specificallyHandledBlock(); 
     } finally { 
      specificallyHandleInProgress = false; 
     } 
    }; 

    var responseError = function (rejection) { 

     // Create the variable for handling errors 
     var shouldHandle = (rejection && rejection.config && rejection.config.headers && rejection.config.headers['handle-generic-errors']); 

     // If we should handle an error 
     if (shouldHandle) { 

      // Get our error 
      var error = service.process(rejection); 

      // Assign our error to the rootScope 
      $rootScope.serverError = error; 

      // Redirect to our error screen 
      $injector.get('$state').transitionTo('error'); 
     } 

     // Fallback, reject the promise 
     return $q.reject(rejection); 
    }; 

    return { 
     specificallyHandled: specificallyHandled, 
     responseError: responseError 
    }; 
}]) 

Я поставил это в моем приложении конфигурации, как это:

.config(['$httpProvider', '$provide', function ($httpProvider, $provide) { 
    $httpProvider.interceptors.push('RequestsErrorHandler'); // Add our interceptor to handle http requests 

    // Decorate $http to add a special header by default 
    function addHeaderToConfig(config) { 
     config = config || {}; 
     config.headers = config.headers || {}; 

     // Add the header unless user asked to handle errors himself 
     if (!specificallyHandleInProgress) { 
      config.headers['handle-generic-errors'] = true; 
     } 

     return config; 
    } 

    // The rest here is mostly boilerplate needed to decorate $http safely 
    $provide.decorator('$http', ['$delegate', function ($delegate) { 
     function decorateRegularCall(method) { 
      return function (url, config) { 
       return $delegate[method](url, addHeaderToConfig(config)); 
      }; 
     } 

     function decorateDataCall(method) { 
      return function (url, data, config) { 
       return $delegate[method](url, data, addHeaderToConfig(config)); 
      }; 
     } 

     function copyNotOverriddenAttributes(newHttp) { 
      for (var attr in $delegate) { 
       if (!newHttp.hasOwnProperty(attr)) { 
        if (typeof ($delegate[attr]) === 'function') { 
         newHttp[attr] = function() { 
          return $delegate.apply($delegate, arguments); 
         }; 
        } else { 
         newHttp[attr] = $delegate[attr]; 
        } 
       } 
      } 
     } 

     var newHttp = function (config) { 
      return $delegate(addHeaderToConfig(config)); 
     }; 

     newHttp.get = decorateRegularCall('get'); 
     newHttp.delete = decorateRegularCall('delete'); 
     newHttp.head = decorateRegularCall('head'); 
     newHttp.jsonp = decorateRegularCall('jsonp'); 
     newHttp.post = decorateDataCall('post'); 
     newHttp.put = decorateDataCall('put'); 

     copyNotOverriddenAttributes(newHttp); 

     return newHttp; 
    }]); 
}]) 

сейчас, это работает отлично. Но это начало раздражать переход к новому представлению для каждой необработанной ошибки. Так что вместо этого я думал, что я мог бы сделать это как ошибку toastr вместо этого, так что я изменил мою службу к этому:

.factory('RequestsErrorHandler', ['ErrorService', 'toastr', function (service, toastr) { 
    var specificallyHandled = function (specificallyHandledBlock) { 
     specificallyHandleInProgress = true; 

     try { 
      return specificallyHandledBlock(); 
     } finally { 
      specificallyHandleInProgress = false; 
     } 
    }; 

    var responseError = function (rejection) { 

     // Create the variable for handling errors 
     var shouldHandle = (rejection && rejection.config && rejection.config.headers && rejection.config.headers['handle-generic-errors']); 

     // If we should handle an error 
     if (shouldHandle) { 

      // Get our error 
      var error = service.process(rejection); 

      // Display the error 
      toastr.error(error); 
     } 

     // Fallback, reject the promise 
     return $q.reject(rejection); 
    }; 

    return { 
     specificallyHandled: specificallyHandled, 
     responseError: responseError 
    }; 
}]) 

, но когда я пытаюсь запустить это, я получаю сообщение об ошибке с указанием:

круговая зависимость найдено: $ HTTP < - $ templateRequest < - $$ animateQueue < - $ анимировать < - toastr < - RequestsErrorHandler < - $ HTTP < - $ templateFactory < - $ вид < - $ состояние

Я не уверен, как это исправить, знает ли кто-нибудь еще?

ответ

4

Есть два простых способа Солев такого рода проблемы круговой зависимости

  1. отвязать услуги, используя события: при обнаружении ошибки в перехватчик, широковещательный событие (с информацией об ошибке) на корневой области. В службе toastr (или в службе, использующей toastr), прослушайте эти события в корневой области и покажите их.
  2. вместо того, чтобы вводить тоастр в перехватчик, впрыскивать службу инжектора. И когда вам нужен экземпляр toastr, вызовите $injector.get('toastr').
+0

Благодарим за решение. Можете ли вы дать краткое объяснение? Я успешно реализовал вариант № 2 и хочу быть уверенным в том, что мешает нам нормальный подход DI. – TrazeK