2012-12-06 109 views
15

我試圖在每次啓動ajax調用時觸發$ rootScope上的事件。AngularJS:每次啓動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'); 
    }); 
}); 

事件 'httpCallStarted' 它沒有被解僱。我懷疑在配置塊中使用$ rootScope或任何其他實例服務是不正確的。如果是這樣,那麼每次http調用開始時我怎麼能得到一個事件,而不必在每次打電話時都傳遞一個配置對象?

在此先感謝

+0

我很確定對angular.injector(['ng'])的調用是你錯誤的地方。這並不能讓您回想起應用程序實際使用的注入器功能,因此當您嘗試獲取$ rootScope時,實際上獲得的是與您認爲的不同的$ rootScope。我知道如何獲得真正的注射器的唯一方法是通過使用angular.element(someselector).injector(),然後您可以調用.get('$ rootScope')。我不知道你在配置塊中是否仍然有問題。 –

回答

16

你總是可以在一個服務包$ HTTP。由於服務只設置一次,您可以讓服務工廠爲您設置事件。老實說,這對我來說有點不好意思,但這是一個很好的解決方法,因爲Angular還沒有一種全球化的方法來做到這一點,除非1.0.3中增加了我不知道的東西。

Here's a plunker of it working

而這裏的代碼:

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

它看起來不錯,但是如何解決$ resource服務中的問題,因爲它取決於$ http而不是自定義的httpPreConfig? – bfcamara

+0

我*認爲*在第一次引用此服務後,它將更新所有對$ http的調用的默認值,甚至是$ resource中的所有調用的默認值。 –

+0

它的工作原理。非常感謝你,謝謝 – bfcamara

12

我已經驗證,當你想到這個代碼將工作。正如我上面提到的,您不會檢索您認爲自己是的注射器,並且需要檢索用於您的應用的注射器。

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

這是正確的答案。 –

+1

要完全正確,您需要接收數據參數並返回一些數據。 – bfcamara

3

要做到這一點,最好的方法是使用http攔截器。檢查this鏈接

11

Cagatay是正確的。更好地利用$http攔截器:

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

我覺得interceptors作品1.1.x中後版本該版本之前有responseInterceptors

+0

我的答案中沒有添加示例,但是,這正是我在項目中使用的。 –

+1

這是一個非常好的答案。我不得不在攔截器中使用一個服務(顯示/隱藏微調器),但是我使用.config來顯示它,並且不可能在.config中使用服務,現在使用這個解決方案,一切都可以正常工作並且很好! –

+0

這應該是正確的答案 – MilesStanfield

相關問題