Angular $http Interceptor открывает несколько модалов при сбое аутентификации
Я использую $http interceptor
показать модальный логин, когда $auth
выходит из строя. Вот краткая настройка, которую я имею:
$provide.factory('modalWhenLoggedOut', ['$q', '$injector', '$rootScope',
function($q, $injector, $rootScope) {
return {
responseError: function(rejection) {
// $injector.get to fix circular dependency error
var loginModal = $injector.get('LoginModalService');
var $http = $injector.get('$http');
var $state = $injector.get('$state');
// Check for reasons instead of status code
var rejectionReasons = ['token_not_provided', 'token_expired', 'token_absent', 'token_invalid'];
// Loop through each rejection reason and redirect
angular.forEach(rejectionReasons, function(value, key) {
if(rejection.data.error === value) {
// Show the login modal
var deferred = $q.defer();
loginModal()
.then(function () {
deferred.resolve( $http(rejection.config) );
})
.catch(function () {
$state.go('index');
deferred.reject(rejection);
});
return deferred.promise;
}
});
return $q.reject(rejection);
}
}
}]);
// Push the new factory onto the $http interceptor array
$httpProvider.interceptors.push('modalWhenLoggedOut');
Приведенный выше код работает нормально. Но проблема, с которой я столкнулся, заключается в том, что, когда API выдает многократную ошибку аутентификации, перехватчик одновременно открывает несколько модальных модов. Обычно на 1 странице у меня может быть 2-3 раза различные сервисы, связывающиеся с API бэкэнда, и когда происходит сбой аутентификации, все эти API возвращают ошибку аутентификации при неверных токенах. Этот перехватчик обнаруживает 3 ошибки take_invalid и показывает 3 модальных имени входа 1 друг на друга. Как мне это предотвратить?
Как я могу убедиться, что перехватчик показывает только 1 модальный логин, независимо от того, сколько раз произошел сбой аутентификации?
Мой сервис выглядит примерно так:
.service('LoginModalService', ['$modal', '$rootScope',
function($modal, $rootScope) {
function updateRootScope() {
$rootScope.loginProgress = false;
}
if ($rootScope.loginProgress = false) {
return function() {
var instance = $modal.open({
templateUrl: rootPath + 'views/partials/LoginModalTemplate.html',
controller: 'LoginModalCtrl'
})
return instance.result.then(updateRootScope);
};
}
}])
В сервисе я пытаюсь использовать $rootScope.loginProgress
в качестве переключателя, чтобы выяснить, открыт модальный логин или нет. Тем не менее, я не уверен, как вернуть пустое обещание, если модальное уже открыто (когда $rootScope.loginProgress
правда).
1 ответ
Чтобы преодолеть мою проблему, я сейчас использую http-auth-interceptor
перехватчик, а затем изменение $rootScope.loginProgress
в зависимости от статуса открытого модального логина. Последовательные модалы, которые открываются из-за нескольких 401-х, будут проверять этот модальный статус входа в систему и затем решают открыть модальное или нет. С помощью http-auth-interceptor
Я могу добавить переключатель, наблюдая за 'event:auth-loginRequired'
, Вот код, который я использую:
scope.$on('event:auth-loginRequired', function() {
if(!$rootScope.loginProgress) {
$rootScope.loginProgress = true;
LoginModalService()
.then(function () {
authService.loginConfirmed();
$rootScope.loginProgress = false;
})
.catch(function () {
authService.loginCancelled();
$rootScope.loginProgress = false;
});
}
});
куда LoginModalService()
это сервис, который открывает модальный логин