AngularJS: нужно запускать событие каждый раз, когда запускается вызов ajax
Я пытаюсь запустить событие на $rootScope каждый раз, когда запускается вызов 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 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-вызов, без необходимости передавать объект конфигурации каждый раз, когда я звоню?
Заранее спасибо
Ответы
Ответ 1
Вы всегда можете обернуть $http в службу. Поскольку службы настроены только один раз, вы можете просто настроить службу factory для вас. Мне кажется, это немного грубо, но это хорошая работа, так как Angular не имеет глобального способа сделать это, если в 1.0.3 ничего не было добавлено, о чем я не знаю.
Здесь работает plunker.
И вот код:
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');
};
});
Ответ 2
Я проверил, что этот код будет работать так, как вы ожидаете. Как я уже упоминал выше, вы не получаете инжектор, который, по вашему мнению, вам нужен, и вам нужно получить тот, который используется для вашего приложения.
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;
});
});
Ответ 3
Кагатай прав. Лучше использовать перехватчики $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
.
Ответ 4
Лучший способ сделать это - использовать HTTP-перехватчик. Отметьте эту ссылку