0

I'm doing an angularjs project and encountered a problem:

I had a service for maintain user's login status. on the stage of the service get loaded, I want it could check whether the user is logged in, and load the user info if they are:

angular.module('tripod')
  .factory('UserService', ['$http', function($http) {

    var self = this,
      userId = angular.element(document.querySelector('#info-base')).attr('data-id');

    if (userId)
      $http.get('/session').then(function(response) {
        self.user = response.data;
      });

    return {

      user: self.user,

      signup: function(user) {
        return $http.post('/signup', user);
      },

      login: function(user) {
        var self = this;
        return $http.post('/login', user).then(function(response) {
          self.user = response.data;
          return self.user;
        });
      },

      logout: function() {
        return $http.get('/logout').then(function() {
          self.user = null;
        });
      },

      session: function() {
        var self = this;
        return $http.get('/session').then(function(response) {
          self.user = response.data;
          return response;
        });
      }
    };

  }]);

the data-id in the info-base is user's id, if they are logged in, the data-id will have value embedded, and their profile will reside in server's session, then I want get their profile through a http request. in factory's return value, I set a property point to the user info, and thought that I could use it later.

but when I refer UserService.user, I got undefined. I know the http promise won't return immediately, I tried set a long timeout, make sure the http promise returned. but the value of UserService.user still undefined.

And yeah, I did search around like this, but I just want know why the code above not working.

please someone teach me, thanks.

Community
  • 1
  • 1
Hetfield Joe
  • 1,443
  • 5
  • 15
  • 26
  • I had a similar issue. Javascript is async and short answer your attribute user should return a promise. That way you could get the user with something like UserService.user().then(...). If that's not enough for you (it was not for me), I reccomend you using ngRoute or ui-router 'resolve' option so your controller will only existis after the promise have been resolved. Does that make sense for you? – Norbor Illig Mar 19 '15 at 14:03
  • Thanks Robson, your advice completely make sense. but I want know why it not working. I'm still learning angularjs, make this clear will help me a lot. – Hetfield Joe Mar 19 '15 at 14:09

1 Answers1

0

Please try this:

angular.module('tripod')
  .factory('UserService', ['$http', '$q', function ($http, $q) {
     var self = this,
       userId = angular.element(document.querySelector('#info-base')).attr('data-id');

     return {
        user: function(){
           var d = $q.defer();

           if (userId)
              $http.get('/session').then(function (response) {
                 self.user = response.data;
                 d.resolve(self.user);
              });
           return d.promise;
        }
     };
  }]).controller('myCtrl', function (UserService) {

     UserService.user().then(function (user) {
        // get your user here
     });
  });

I have removed some functions to focus only on the important issue. Note that now user is a function which returns a promise(https://docs.angularjs.org/api/ng/service/$q). In you controller you'll get the value inside the 'then' block, wich will be triggered when d.resolve(sel.user) inside your service is called.

Norbor Illig
  • 658
  • 6
  • 14