Search code examples
javascriptangularjsangularjs-factoryangularjs-http

Able to access object returned by service, but accessing its properties gives undefined


I'm an angular beginner and I'm trying to set up a factory that gets data from my php back-end and updates the controller. Here is my basic code:

factory

app.factory('sessionStatus', ['$http', function($http){
    return {
        status:function(){
            var status = {};
            $http.get('/game_on/api/api.php?session-status')
            .then(function(response){
                angular.copy(response.data, status);
            });
            return status;
        }
    };
}]);

controller

app.controller('headerCtrl', ['$scope', 'sessionStatus', function($scope, sessionStatus){

    $scope.sessionStatus = sessionStatus.status();

    console.log($scope.sessionStatus);

}]);

This gives me the following in the console:

Object{}
  session:"false"

However, when I adjust the controller to log the value of the session property like so:

console.log($scope.sessionStatus.session);

I simply get undefined in the console.

What am I doing wrong?

EDIT

For anyone else who suffers from my distinct brand of retardation, here's the conclusion I've reached:

The main cause of the issue is that I've been trying to access asynchronously generated information returned by the $http service before its promise has been resolved (i.e. before .then() is finished executing), which is leading to undefined being logged because the data has literally not yet been defined since the request that generates it is still in progress by the time console.log() is called in the controller.

Using the $timeout service I was able to delay the calling of console.log(), which resulted in the data being correctly logged to the console.

$timeout(function(){
    console.log($scope.sessionStatus.session);
}, 2000); // logs "false" to the console like originally expected

My previous thinking was that I should make the call to my factory method as short as possible within the controller, and then act upon its results outside of that call. This was obviously a bad idea because .then() exists so that you can act on the results of an asynchronous request at the precise moment the request is completed.

In hindsight this all seems so obvious, but hopefully this explanation helps someone else in the future...

Thanks for all the answers I received, they were a big help!


Solution

  • since javascript is asynchronous it does't wait until http response and return the status. thats why it return null. try something like this

       app.factory('sessionStatus', ['$http', function($http){
                return {
                    status:function(){
                     $http.get('/game_on/api/api.php?session-status')
                    }
                };
            }]);
    
            app.controller('headerCtrl', ['$scope', 'sessionStatus', function($scope, sessionStatus){
    
                $scope.sessionStatus = sessionStatus.status().then(function(response) { 
                   console.log(response);
            });
    
    
        }]);