2

I have a 'userSessionDataService'. This fetches the user's details from the server (ONLY ONCE).

I want the user data to be accessible when the service is called, but without the need to call .then() on a promise.

From what I understand this is not supported by angular. The caller of the service must always use a promise to access data that were loaded asynchronously (e.g.through ajax).

Marinos An
  • 9,481
  • 6
  • 63
  • 96
  • 1
    I agree that this is not possible. I don't know that this is a design that you really want anyway--causing your application to block at a fundamental level waiting for an asynchronous resource. – John Bledsoe Jan 29 '14 at 14:44
  • I had the same issue. I solved it and am working on my answer. Give me a couple minutes. – Nathaniel Johnson Jan 29 '14 at 14:46
  • 1
    Easier to provide this link:http://stackoverflow.com/questions/16286605/initialize-angularjs-service-with-asynchronous-data – Nathaniel Johnson Jan 29 '14 at 14:58
  • What I did is different. I store the user data in `localStorage` when they login in. On startup, I check if it is in localStorage and it has not expired. If it is missing or expired, I use `$location.path('/SignIn');` inside `module().run()` If you are still interested I can cobble together how I do it in an answer. – Nathaniel Johnson Jan 29 '14 at 15:02
  • @Nathaniel Johnson What I can understand from the link above is that I will need to use resolve in every route which requires userSessionDataService? Which means everywhere. – Marinos An Jan 29 '14 at 15:08
  • yes, that is the BIG downside of it. – Nathaniel Johnson Jan 29 '14 at 15:21
  • in fairness though, you can just resolve in the routes that will be used at initialization. I use two in my apps (loggedIn vs not loggedIn) – Nathaniel Johnson Jan 29 '14 at 15:30
  • @Nathaniel Johnson I don't exactly get this. What if I am in anyView and user refreshes his browser? I want him to stay in the same page. In order for this to happen I need a mechanism to fetch again the session object, before route matches anyView. – Marinos An Jan 29 '14 at 16:35

1 Answers1

3

You may find useful to manually bootstrap like I did for localisation:

$(function(){
    $.ajax({
        url: "/GetResources",
        type: "POST",
        dataType: 'json',
        contentType: "application/json; charset=utf-8",
        success: function(result) {
            var mn = 'app';
            angular.module(mn).value('Resources', result);
            angular.bootstrap(document, [mn]);
        }
    });
});

Resources are always available this way:

angular.module('app').run(function($rootScope, Resources){
     $rootScope.resources = Resources;
});
karaxuna
  • 26,752
  • 13
  • 82
  • 117
  • I just wonder why such an initialization is not supported in angular lifecycle. – Marinos An Jan 29 '14 at 15:13
  • I like this answer. I would only add that you can do something similar in `module().config()` and so have access to `$http` and the promise will be fulfilled by the time that `module().run()` is executed. – Nathaniel Johnson Jan 29 '14 at 15:35
  • @Nathaniel Johnson is it possible that you post an answer with such a code? – Marinos An Jan 29 '14 at 15:40
  • Sure, give me a little bit so I can create a plunker too. – Nathaniel Johnson Jan 29 '14 at 15:41
  • So I tried a solution using pure Angular and failed. The task queue doesn't execute between Angular.module.run and loading of the controller. This solution is the closest I could get without interrupting the bootstrap process. Sorry :-( – Nathaniel Johnson Jan 29 '14 at 17:34
  • 1
    Here is the plunkr I was messing with if you want to repost. http://plnkr.co/edit/aIMMoBd78hqTvtPeL2Nx?p=preview – Nathaniel Johnson Jan 29 '14 at 17:35