What I'm trying to achieve
I would like to to transition to a certain state (login) in case an $http request returns a 401 error. I have therefore created an $http interceptor.
The problem
When I am trying to insert '$state' into the interceptor I get a circular dependency. Why and how do i fix it?
Code
//Inside Config function
var interceptor = ['$location', '$q', '$state', function($location, $q, $state) {
function success(response) {
return response;
}
function error(response) {
if(response.status === 401) {
$state.transitionTo('public.login');
return $q.reject(response);
}
else {
return $q.reject(response);
}
}
return function(promise) {
return promise.then(success, error);
}
}];
$httpProvider.responseInterceptors.push(interceptor);
Use the $injector
service to get a reference to the $state
service.
var interceptor = ['$location', '$q', '$injector', function($location, $q, $injector) {
function success(response) {
return response;
}
function error(response) {
if(response.status === 401) {
$injector.get('$state').transitionTo('public.login');
return $q.reject(response);
}
else {
return $q.reject(response);
}
}
return function(promise) {
return promise.then(success, error);
}
}];
$httpProvider.responseInterceptors.push(interceptor);
angular-ui-router injects the $http
service as a dependency into $TemplateFactory
which then creates a circular reference to $http
within the $httpProvider
itself upon dispatching the interceptor.
The same circular dependency exception would be thrown if you attempt to inject the $http
service directly into an interceptor like so.
var interceptor = ['$location', '$q', '$http', function($location, $q, $http) {
Circular dependency exceptions can indicate that there is a mixing of concerns within your application which could cause stability issues. If you find yourself with this exception you should take the time to look at your architecture to ensure you avoid any dependencies that end up referencing themselves.
I agree with the answer below that using the $injector
to directly get a reference to the desired service is not ideal and could be considered an anti pattern.
Emitting an event is a much more elegant and also decoupled solution.