2012-12-06 9 views
15

Próbuję wywołać zdarzenie na $ rootScope za każdym razem, gdy wywoływane jest wywołanie ajax.AngularJS: potrzeba wywoływania zdarzenia za każdym razem, gdy wywoływane jest wywołanie ajax

var App = angular.module('MyApp'); 

App.config(function ($httpProvider) { 
    //add a transformRequest to preprocess request 
    $httpProvider.defaults.transformRequest.push(function() { 
     //resolving $rootScope manually since it's not possible to resolve instances in config blocks 
     var $rootScope = angular.injector(['ng']).get('$rootScope'); 
     $rootScope.$broadcast('httpCallStarted'); 

     var $log = angular.injector(['ng']).get('$log'); 
     $log.log('httpCallStarted'); 
    }); 
}); 

Zdarzenie "httpCallStarted" nie jest uruchamiane. Podejrzewam, że nie jest właściwe używanie $ rootScope lub jakiejkolwiek innej usługi instancji w blokach konfiguracji. Jeśli tak, jak mogę uzyskać zdarzenie za każdym razem, gdy rozpoczyna się wywołanie http, bez konieczności przekazywania obiektu konfiguracyjnego za każdym razem, gdy wykonuję połączenie?

Z góry dziękuję

+0

Jestem prawie pewny, że wywołania do kątowego injektora (['ng']) są tam, gdzie idziesz źle. To nie daje ci funkcji wtryskiwacza, która jest aktualnie używana z twoją aplikacją, więc kiedy próbujesz uzyskać $ rootScope, dostajesz inny $ rootScope niż ten, którym myślisz, że jesteś. Jedyny sposób, w jaki wiem, jak uzyskać prawdziwy wtryskiwacz, to użycie funkcji angle.element (someselector) .injector(), a następnie możesz wywołać .get ("$ rootScope") na ten temat. Nie wiem jednak, czy nadal będziesz mieć problemy z robieniem tego w bloku konfiguracji. –

Odpowiedz

16

Zawsze można zawijać http w usłudze. Ponieważ usługi są konfigurowane tylko raz, możesz po prostu skonfigurować fabrykę usług dla ciebie. Czuję się trochę hackish do mnie, szczerze mówiąc, ale to dobra robota dookoła, ponieważ Angular nie ma globalnego sposobu, aby to zrobić jeszcze, chyba że coś jest dodane w 1.0.3, którego nie jestem świadomy.

Here's a plunker of it working

A oto kod:

app.factory('httpPreConfig', ['$http', '$rootScope', function($http, $rootScope) { 
    $http.defaults.transformRequest.push(function (data) { 
     $rootScope.$broadcast('httpCallStarted'); 
     return data; 
    }); 
    $http.defaults.transformResponse.push(function(data){ 
     $rootScope.$broadcast('httpCallStopped'); 
     return data; 
    }) 
    return $http; 
}]); 

app.controller('MainCtrl', function($scope, httpPreConfig) { 
    $scope.status = []; 

    $scope.$on('httpCallStarted', function(e) { 
    $scope.status.push('started'); 
    }); 
    $scope.$on('httpCallStopped', function(e) { 
    $scope.status.push('stopped'); 
    }); 

    $scope.sendGet = function(){ 
    httpPreConfig.get('test.json');  
    }; 
}); 
+0

Wygląda miło, jednak jak rozwiązać problem w usłudze $ resource, ponieważ zależy on od $ http, a nie od niestandardowego httpPreConfig? – bfcamara

+0

Ja * myślę * po pierwszym odwołaniu się do tej usługi, zaktualizuje ona wartości domyślne dla wszystkich połączeń do $ http, nawet tych w zasobach $. –

+0

To działa. Bardzo dziękuję. – bfcamara

12

I sprawdzeniu, że ten kod zadziała zgodnie z oczekiwaniami. Jak wspomniałem powyżej, nie pobierasz wtryskiwacza, o którym myślisz, że jesteś i potrzebujesz pobrać ten, który jest używany w twojej aplikacji.

discussionApp.config(function($httpProvider) { 
    $httpProvider.defaults.transformRequest.push(function(data) { 
    var $injector, $log, $rootScope; 
    $injector = angular.element('#someid').injector(); 

    $rootScope = $injector.get('$rootScope'); 
    $rootScope.$broadcast('httpCallStarted'); 

    $log = $injector.get('$log'); 
    $log.log('httpCallStarted'); 
    return data; 
    }); 
}); 
+2

To jest poprawna odpowiedź. –

+1

Aby być całkowicie poprawnym, musisz otrzymać argument danych i zwrócić również niektóre dane. – bfcamara

3

Najlepszym sposobem na to jest użycie przechwytywacza HTTP. Sprawdź this link

11

Cagatay ma rację. Lepsze wykorzystanie $http przechwytujące:

app.config(function ($httpProvider, $provide) { 
    $provide.factory('httpInterceptor', function ($q, $rootScope) { 
     return { 
      'request': function (config) { 
       // intercept and change config: e.g. change the URL 
       // config.url += '?nocache=' + (new Date()).getTime(); 
       // broadcasting 'httpRequest' event 
       $rootScope.$broadcast('httpRequest', config); 
       return config || $q.when(config); 
      }, 
      'response': function (response) { 
       // we can intercept and change response here... 
       // broadcasting 'httpResponse' event 
       $rootScope.$broadcast('httpResponse', response); 
       return response || $q.when(response); 
      }, 
      'requestError': function (rejection) { 
       // broadcasting 'httpRequestError' event 
       $rootScope.$broadcast('httpRequestError', rejection); 
       return $q.reject(rejection); 
      }, 
      'responseError': function (rejection) { 
       // broadcasting 'httpResponseError' event 
       $rootScope.$broadcast('httpResponseError', rejection); 
       return $q.reject(rejection); 
      } 
     }; 
    }); 
    $httpProvider.interceptors.push('httpInterceptor'); 
}); 

myślę interceptors prace dla wersji po 1.1.x. Przed tą wersją był responseInterceptors.

+0

Nie dodałem przykład w mojej odpowiedzi, ale tak jest dokładnie to, czego używam w moich projektach. –

+1

To jest bardzo dobra odpowiedź. Musiałem użyć usługi (pokazać/ukryć spinner) wewnątrz przechwytywacza, ale użyłem .config, aby to pokazać, i nie można korzystać z usługi w .config, teraz z tym rozwiązaniem wszystko działa sprawnie i dobrze! –

+0

To powinna być właściwa odpowiedź. – MilesStanfield

Powiązane problemy