1

I know I can resolve certain dependencies for a controller based on the route. However, I have a service that I always want to be resolved: The current user.

The service basically does a get request to the server for the current user (url is something like /api/user/me) and returns an object with the userid, name etc. This is currently cached and returned with promises, so everywhere I want to use it I have to do something like:

CurrentUser.getCurrentUser().then(function(user) {
    // use user.id here
});

creating an extra, unnecessary layer of nesting and callbacks for data that is already loaded. Is there a nice way I can preload the user globally so I can use it everywhere without having to wait for promises?

Something along the lines of the route resolving I linked to above, except that it should work for all routes and possibly services as well.

I picture a result like this:

// somewhere
AlwaysResolveThisBeforeDoingSomething(UserService.resolve);

// In my controller
.controller('CurrentUserCtrl', function ($scope, $http, CurrentUser) {
    // CurrentUser is an initialized user containing id, name etc.
Community
  • 1
  • 1
Matsemann
  • 21,083
  • 19
  • 56
  • 89
  • one approach I've used previously is to not self initialize angular, use third party code like jQuery to make an initial call while "loading" is shown ( could use native methods also), store data in global object, then call angular bootstrap within success callback and pass the global variable to my service – charlietfl Oct 27 '13 at 15:28

2 Answers2

0

One option would be just to let it complete. Your service could have a user property and you could bind to that for what you need. This would be like treating everything like the user was unauthenticated until the service populated the information.

If it is something available when you generate the page, why not include it in the HTML or as a <SCRIPT> tag? In ASP.NET MVC you can do this:

public ActionResult UserScript()
{
    var user = new { 
        id = 1,
        name = "jason"
    };
    string s = string.format("var my = {{ user: {0} }};", 
            JsonConvert.SerializeObject(user));
    return JavaScript(s);
}

And it will get loaded in the same order as any script on your page depending on where you put it, but you can put it after your scripts because the value won't matter until angular bootstraps. Here I just set the value simply, but you could make it part of a service.

<div ng-app ng-controller="MyCtrl">
    <script type="text/javascript">
        function MyCtrl($scope) {
            $scope.user = my.user;
        }
    </script>
    <h3>You are: {{user.name}}</h3>
</div>
<script type="text/javascript" src="@Url.Action("UserScript", "Test")"></script>
Jason Goemaat
  • 28,692
  • 15
  • 86
  • 113
0

You are using $http so I would solve this using interceptors.

Taken from the angularjs docs section Interceptors http://docs.angularjs.org/api/ng.$http

For purposes of global error handling, authentication, or any kind of synchronous or asynchronous pre-processing of request or postprocessing of responses, it is desirable to be able to intercept requests before they are handed to the server and responses before they are handed over to the application code that initiated these requests. The interceptors leverage the promise APIs to fulfill this need for both synchronous and asynchronous pre-processing.

Here is something you can start with: http://plnkr.co/edit/td0jyy3j3rTAx1mZifjy?p=preview You need to test this code on your local server and configure your server to send a 401 Unauthorized response.

bekite
  • 3,444
  • 2
  • 23
  • 31
  • The basic idea is you access a route that needs some authenticaion. Server responds with a status of 401. You show a login form and if the user was sucessfully authenticated resend the failed request to the server. Take a look at this post https://espeo.pl/authentication-in-angularjs-application/ and at the source code here https://github.com/witoldsz/angular-http-auth/blob/master/src/http-auth-interceptor.js – bekite Oct 27 '13 at 23:17
  • I should mention that the blog post describes how to do this using the old Response interceptors which is deprecated. – bekite Oct 27 '13 at 23:21
  • But the problem isn't authentication, it's just preloading of data. I already have an interceptor listening for 401's (https://github.com/Studentmediene/Momus/blob/develop/src/main/webapp/app/js/services/httpInterceptor.js) – Matsemann Oct 27 '13 at 23:51
  • But if the user is authenticated once the CurrentUser is prefilled with data. You could call instantiate your CurrentUser server arround line 76 in your git file – bekite Oct 27 '13 at 23:59
  • Sry couldn't edit my last comment anymore. That's what I meant: You could instantiate your CurrentUser service arround line 76 in your git file. – bekite Oct 28 '13 at 00:09