Правильный способ отключить / удалить перехватчики http в Angular?
Я последовал за этим постом, чтобы реализовать похожий образ загрузчика ajax в проекте:
Моя реализация имеет несколько отличий:
- я использую
$rootScope
вemit
и неbroadcast
и я тоже использую$rootScope
на директиву для обработки события. - Из-за специфики проекта я должен отменить привязку
$rootScope.$on
слушатели сразу после запуска первого события (либо для показа, либо для скрытия) внутри обработчика события. - Я запускаю только одно шоу / скрыть событие. Показать по первому HTTP-запросу, скрыть, когда счетчик достигнет 0.
Я считаю, что это основные отличия от связанного поста, не уверен, имеют ли они отношение к моему вопросу, но на всякий случай...
Когда обрабатывается событие скрытия загрузчика, загрузчик исчезает, и я не буду показывать его снова, пока страница не будет обновлена, но у меня все еще есть фоновые запросы http для обновления данных на текущей странице. Эти запросы будут по-прежнему перехватываться и запускать новые события show / hide, которые больше не требуются / не обрабатываются. Мне нужно только первое шоу и сначала спрятаться, вот и все.
Как правильно удалить перехватчик HTTP, который я добавил в $httpProvider
после первого события скрытия?
Я знаю, что мы добавляем перехватчик, используя $httpProvider.interceptors.push()
но я не уверен, как вытащить его, когда мне больше не нужен этот перехватчик.
2 ответа
Я собирался назначить награду за это, так как у меня был тот же вопрос. Однако.... похоже, что interceptors
а также responseInterceptors
это просто массивы, в соответствии с исходным кодом (строки 127 и 133 в $httpProvider
завод). Там нет обертки вокруг этого.
Из того, что я могу сказать, вы должны были бы использовать pop()
или любой другой метод массива. Тем не менее, это означает, что вы не знаете, что вы хлопаете! Хранение ссылки на объект на самом деле не поможет, потому что вы не можете сделать массивную функцию для него, если не решите выполнить итерацию на основе равенства (что может работать, используя indexOf или что-то еще, например Underscore).
Действительно, Angular нужна обертка для этого, так как вы не можете быть уверены, что ваш перехватчик является последним в списке.
Лучшее решение, которое я нашел, - это то, что объяснил jedd.ahyoung в своем комментарии.
Это шаги.
Добавьте две пользовательских фабрики
angular.module('myModule.services', [])
/**
* Save application information.
*/
.factory('Application', function($log) {
return {};
})
/**
* Custom Http Interceptor for the loader.
*/
.factory('myHttpInterceptor', function($rootScope, $q, Application) {
return {
request: function(config) {
if(Application.enableLoader){
$rootScope.$broadcast('loading:show');
}
return config;
},
requestError: function(rejection) {
$rootScope.$broadcast('loading:hide');
return $q.reject(rejection);
},
response: function(response) {
$rootScope.$broadcast('loading:hide');
return response;
},
responseError: function(rejection) {
$rootScope.$broadcast('loading:hide');
return $q.reject(rejection);
}
};
});
Добавьте его в свой config
шаг
.config(function($httpProvider) {
//loading interceptor
$httpProvider.interceptors.push('myHttpInterceptor');
});
Включить / отключить, когда / где вы хотите
Application.enableLoader = true;
$http({
url: url,
method: "GET"
}).success(function(data){
$log.log("Data received and my loader is already closed :)");
Application.enableLoader = false;
$scope.retrieveBooks();
}).error(function(){
$log.log("Error, but my loader is already closed :)");
Application.enableLoader = false;
$scope.retrieveBooks();
});
$scope.retrieveBooks = function(){
$http({
url: url,
method: "GET"
}).success(function(data){
$log.log("Data received and my loader is not closed :(");
}).error(function(){
$log.log("Error, but my loader is not closed :(");
});
};