3

I've wrapped up my REST API in an AnguarJS service that gets injected into controllers. Pretty standard, right. Now I'd like that service to intercept any 401 response and somehow trigger a logout or re-login prompt or something. The problem is: that service doesn't have access to any scope. What is the best way to broadcast that error? I've come up with a few ideas, but I'm new to Angular and am wondering if anyone can tell me the "Angular" way of doing this?

1) I could have the service act as an event pool that my AppCtrl can listen to. But this seems a bit overly complicated. So:

myService.on('logout', function() { 
    $scope.isLoggedIn = false;
});

2) I can inject the $rootScope into the service, and have the service modify isLoggedIn directly. But this just seems plain wrong. I'd like to keep clear distinctions where services service data, controllers control the scope, and directives muck with the dom.

3) Every one of my controllers could watch for a rejected promise and if the reason is a 401 error, then reach up the $scope and set isLoggedIn to false, but this option just sucks, obviously.

Any help?

Thanks.

2
  • From where does the logout action need to happen? How will the user be shown a login form or be notified? Is there a redirect? Commented Apr 2, 2013 at 21:06
  • @JoshDavidMiller That's a good question. Where should that happen. The whole thing is a one-page app, so no redirects. I'm imagining an isLoggedIn variable on the scope that controls an ngSwitch or something that either shows the App or a Login screen. Does that make sense? Commented Apr 2, 2013 at 21:14

1 Answer 1

4

There are three components we need to get communicating; you already know there's the controller where the ngSwitch takes place and there's the API service. The third is some type of user state service that you use to manage user info. This type of service is very common in AngularJS apps. See this answer for an idea of what that service might look like.

Your API service would, on 401, tell that service that we are currently logged out. You could also use a generic $http interceptor for this, but it would affect all $http calls. Your choice here.

Your controller then only has to watch for this current state:

$scope.$watch( AuthService.isLoggedIn, function ( isLoggedIn ) {
  $scope.isLoggedIn = isLoggedIn;
});

And your template can use ngShow on that scope variable:

<div class="login" ng-show="!isLoggedIn">
  ...
</div>

This service is also available to any controller that needs it. Your API service can even check the value before issuing any requests to prevent any unnecessary API calls if we have a priori knowledge the user isn't logged in.

There are countless variations on this that depend on your app's structure and your existing code, but hopefully this will set you on the right path.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.