web-dev-qa-db-fra.com

Dépendance circulaire trouvée: $ http <- $ templateFactory <- $ view <- $ state

J'ai un contrôle 401 actuel que je cours avec $ location qui fonctionne bien. Cependant, j'aimerais l'échanger vers $ state et utiliser ui-router à la place. Quand je le fais, je reçois un code d'erreur tel que:

Circular dependency found: $http <- $templateFactory <- $view <- $state <- authHttpResponseInterceptor <- $http <- $compile

Mon code actuel est correct car je vérifie certains chemins et n'autorise aucun utilisateur connecté à les afficher:

  /* Look for 401 auth errors and then redirect */
  .factory('authHttpResponseInterceptor',['$q','$location', function($q,$location) {

      return {
          response: function(response){
              if (response.status === 401) {
              }

              return response || $q.when(response);
          },
          responseError: function(rejection) {
              var reservedPaths = ['/','/login','/connect','/event'];
              if (rejection.status === 401 && _.contains(reservedPaths,$location.path().trim())) {
                  $location.path('/welcome');

              }
              return $q.reject(rejection);
          }
      };
  }])
  .config(['$httpProvider',function($httpProvider) {
      //Http Intercpetor to check auth failures for xhr requests
      $httpProvider.interceptors.Push('authHttpResponseInterceptor');
  }]);

Le code que j'ai ajouté est le suivant:

  /* Look for 401 auth errors and then redirect */
  .factory('authHttpResponseInterceptor',['$q','$location', **'$state',** function($q,$location, **$state**) {

      return {
          response: function(response){
              if (response.status === 401) {
              }

              return response || $q.when(response);
          },
          responseError: function(rejection) {
              var reservedPaths = ['/','/mycube','/connect','/event'];
              if (rejection.status === 401 && _.contains(reservedPaths,$location.path().trim())) {
                  **$state.go('home');**

              }
              return $q.reject(rejection);
          }
      };
  }])
  .config(['$httpProvider',function($httpProvider) {
      //Http Intercpetor to check auth failures for xhr requests
      $httpProvider.interceptors.Push('authHttpResponseInterceptor');
  }]);

Pourquoi l’ajout d’État causerait-il ce problème alors que cela fonctionne bien avec l’emplacement? 

35
Mr. BigglesWorth

Il semble que le service $ state entraîne une dépendance circulaire avec le service $ http. Cela peut être dû au fait que templateFactory (voir https://github.com/angular-ui/ui-router/blob/master/src/templateFactory.js ) est injecté avec le service $ http en plus de l'intercepteur lui-même composé avec le service $ http.

Pour résoudre ce problème de dépendance circulaire, vous pouvez utiliser le service $ injector pour connecter le service $ state à votre intercepteur. Voir le code révisé:

/* Look for 401 auth errors and then redirect */
module.factory('authHttpResponseInterceptor', ['$q','$location', '$injector', function($q, $location, $injector) {
    return {
        response: function(response){
            if (response.status === 401) {
            }

            return response || $q.when(response);
        },
        responseError: function(rejection) {
            var reservedPaths = ['/', '/mycube', '/connect', '/event'];
            if (rejection.status === 401 && _.contains(reservedPaths, $location.path().trim())) {
                var stateService = $injector.get('$state');
                stateService.go('home');
            }
            return $q.reject(rejection);
        }
    };
}]);

Vous pouvez en savoir plus sur le service $ injector ici: https://docs.angularjs.org/api/auto/service/ $ injector

IMPORTANT

Je recommanderais d'utiliser les événements de changement d'état (voir https://github.com/angular-ui/ui-router/wiki#state-change-events ) pour surveiller les erreurs en utilisant $ stateChangeError et en inspectant l'erreur de la 401.

76
aaronroberson

Voici la solution la plus simple que j'ai faite et cela a fonctionné. À l'intérieur de l'usine, écrivez:

var $http = $injector.get("$http");

puis utilisez $http comme vous le feriez normalement.

NOTE: Si vous n'avez pas d'injecteur $ disponible dans votre usine, il vous suffit de l'injecter comme suit

.factory('authHttpResponseInterceptor',['$q','$location','$injector', function($q,$location,$injector) {
}])
1
Hari Das