0

I am calling a service method in my controller to return an object. I struggled a lot to figure out the exact implementation difference between a service and a factory.

According to what I learned service instantiates with new and returns this to the calling controller.

I am trying to accomplish the same here..calling a service function in controller and storing the returned object in controller's $scope.user variable as follows:

controller:

app.controller('LoginFormController',['$log','$scope','userAngService','userBean',function($log,$scope,userAngService,userBean){
    $scope.user = {};
    $scope.login = function(val){
        userAngService.login(val);
        $scope.user = userAngService.user;   //accessing service's user variable
        //$scope.user = userAngService.user;
        console.log($scope.user);    //empty object being logged in console
    };
}]);

service:

app.service('userAngService',['$http','$log','$rootScope','$location',function($http,$log,$rootScope,$location){
    this.user = {};
    this.login = function(val){
        console.log('from angular service');
        $http({
            method: 'GET',
            url: 'http://localhost:7070/messenger/webapi/messages'
        }).success(function(data){
            user = data;
            console.log(user);   //successfully logging "user" in console
        });
    };

    return this;
}]);

Above in the service the login function(val) is changing the user variable defined in the service itself.

I can make the function to return this.user but still am getting the same result.

What changes should I make here?

And here is what I am getting in console: console output

0

5 Answers 5

1

You are calling $http service internally on your userAngService service.

Its a asynchronous service call so, just return the promise object to the controller and then assign values to $scope.user.

Controller

    app.controller('LoginFormController',     ['$log','$scope','userAngService','userBean',function($log,$scope,userAngService,userBean){        
    $scope.login = function(val){
        userAngService.login(val).then(function(data){
            $scope.user = data;
            console.log($scope.user);                
        });         
    };
}]);

Service

app.service('userAngService',['$http','$log','$rootScope','$location',function($http,$log,$rootScope,$location){
    this.user = {};
    this.login = function(val){
        console.log('from angular service');
        return $http({
            method: 'GET',
            url: 'http://localhost:7070/messenger/webapi/messages'
        });
    };           
}]);
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you for your answer. But can you explain a lil what exactly was wrong with my service code? as the success function was though returning the user object?
On your code, the success function will definitely return the user object to the controller but it will take some time. During this time-period the main thread will assign values to $scope.user (undefined) and will exit the program loop
I tried what you are suggesting here as $scope.login = function(val){ userAngService.login(val); setTimeout(function(){ $scope.user = userAngService.user; console.log($scope.user); },(5*1000); }; but still it is logging blank object in console. Here I am bypassing the time it will take to update user object in service
on your service inside the success function, assign values to this.user instead of user
1

Service

app.service('userAngService',['$http','$log','$rootScope','$location',function($http,$log,$rootScope,$location){
    this.user = {};
    this.login = function(val){
        console.log('from angular service');
        // here you are returning Promise
        return $http({
            method: 'GET',
            url: 'http://localhost:7070/messenger/webapi/messages'
        }).success(function(data){
            user = data;
            console.log(user);   //successfully logging "user" in console

            return user;
        });
    };
}]);

The first thing is, you don't need to return anything from service. This is the one of the difference from factory. In factory you need to return an object, but no need to return any object in service

controller

app.controller('LoginFormController',['$log','$scope','userAngService','userBean',function($log,$scope,userAngService,userBean){
    $scope.user = {};
    $scope.login = function(val){
        userAngService.login(val).then(userName){
               $scope.user = userName;
               console.log($scope.user);
        };
    };
}]);

1 Comment

Here why do I need to return user variable? If this user is being changed by login function's .success function, and as can also be accessed as this.user, can;t it be accessed directly as $scope.user = userAngService.user??
0

Your controller is logging a blank object which is correct since it is a blank object. Can you try this?

app.service('userAngService',['$http','$log','$rootScope','$location',function($http,$log,$rootScope,$location){
    var vc = this;
    vc.user = {};
    vc.login = function(val){
        console.log('from angular service');
        $http({
            method: 'GET',
            url: 'http://localhost:7070/messenger/webapi/messages'
        }).success(function(data){
            vc.user = data;
            console.log(user);   //successfully logging "user" in console
        });
    };
}]);

OR this...

app.service('userAngService',['$http','$log','$rootScope','$location',function($http,$log,$rootScope,$location){
    var vc = this;
    vc.user = {};
    vc.login = function(val){
        console.log('from angular service');
        $http({
            method: 'GET',
            url: 'http://localhost:7070/messenger/webapi/messages'
        }).success(function(data){
            $rootScope.$apply(function(){vc.user = data;});
            console.log(user);   //successfully logging "user" in console
        });
    };
}]);

1 Comment

Neither of the two worked ! :\ got same blank object following your first approach and errors following the second one.
0

Your Service needs to return an abject. This should work:

app.service('userAngService',['$http','$log','$rootScope','$location',function($http,$log,$rootScope,$location){
this.user = {};
this.login = function(val){
    console.log('from angular service');
    $http({
        method: 'GET',
        url: 'http://localhost:7070/messenger/webapi/messages'
    }).success(function(data){
        user = data;
        console.log(user);   //successfully logging "user" in console
    });
};

return this; 
}]);

or if you want to use private and public funtions (module pattern) in javascript. Do:

    app.service('userAngService',['$http','$log','$rootScope','$location',function($http,$log,$rootScope,$location){

var user = {};

var handleRequestData = function(data){
    user = data;
    console.log(user);   //successfully logging "user" in console
};

var login = function(val){
    console.log('from angular service');
    $http({
        method: 'GET',
        url: 'http://localhost:7070/messenger/webapi/messages'
    }).success(handleRequestData);
};

/* while you returning just the login function, user and handleRequestData stay private */
return {
    login: login
};

}]);

1 Comment

I have tried returning this also. Still the same result. I have updated it in my question also.
0

You have to user promise in order to get data from a service via HTTP request because what happened when your http request give response back to controller there is no handler to receive it.

Controller should be :

app.controller('LoginFormController',['$log','$scope','userAngService','userBean',function($log,$scope,userAngService,userBean){
    $scope.user = {};
    $scope.login = function(val){
        userAngService.login(val).then(function(res){
            $scope.user = res;   
        //$scope.user = userAngService.user;
        console.log($scope.user);
        console.log(userAngService.user);
        });

    };
}]);

Service should be :

app.service('userAngService',['$http','$log','$rootScope','$location', '$q',function($http,$log,$rootScope,$location,$q){
    this.user = {};
    this.login = function(val){
        var deferred = $q.defer();
        var promise = deferred.promise;
        console.log('from angular service');
        $http({
            method: 'GET',
            url: 'http://localhost:7070/messenger/webapi/messages'
        }).success(function(data){
            user = data;
            console.log(user);   //successfully logging "user" in console
            deferred.resolve(user);
        });
        return promise;
    };

    return this;
}]);

I have not tested this code and i think it will work for you but if not the case please let me know.

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.