I recently started working with AngularJS and I'm facing an issue with my interceptor that catches 401 errors from server responses.
When a 401 status is detected, it triggers a "loginRequired" message broadcast and redirects to the login page. However, there's a brief moment where the restricted page flashes before the redirection occurs. I'm still learning about asynchronous operations and promises, so I'd appreciate any guidance on what I might be doing wrong.
Here's the simplified version of my interceptor code:
var app = angular.module('app', []);
app.factory('myInterceptor', ['$q', '$rootScope',
function($q, $rootScope) {
var myInterceptor = {
'responseError': function(rejection) {
$rootScope.$broadcast('event:loginRequired');
return $q.reject(rejection);
}
};
return myInterceptor;
}
]);
Injecting my interceptor:
app.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push('myInterceptor');
}]);
Restricted page route:
.when('/restrictedPage', {
templateUrl: 'partials/restrictedPage.html',
controller: 'RestrictedPageController'
}).
Restricted page controller:
app.controller('RestrictedPageController', function($scope) {
//Alert message sometimes appears, sometimes not
alert("Oops, shouldn't be here");
});
$rootScope event listener:
$rootScope.$on('event:loginRequired', function() {
//Only redirect if we aren't on the free access page
if ($location.path() == "/freeAccess")
return;
//Redirect to the login page otherwise
$location.path('/home').replace();
});
The flashing issue seems to be related to how I handle the interceptor and promises. I came across another approach on GitHub, but it deviates from the official documentation method. While it works without the page flash, I prefer using the factory approach for cleanliness. Any insights on resolving this would be greatly appreciated!
Alternative approach found on GitHub:
var interceptor = ['$rootScope', '$q', '$log',
function(scope, $q, $log) {
function success(response) {
return response;
}
function error(response) {
var status = response.status;
if (status == 401) {
var deferred = $q.defer();
var req = {
config: response.config,
deferred: deferred
};
scope.$broadcast('event:loginRequired');
return deferred.promise;
}
// Otherwise
return $q.reject(response);
}
return function(promise) {
return promise.then(success, error);
};
}
];
$httpProvider.responseInterceptors.push(interceptor);
My goal isn't just to find a quick fix; I want to understand and improve my code. Thank you for your help!