Abaij
Abaij

Reputation: 873

How to make http request in factory

I want to get data from server using angular factory. Here is what I did.

.factory('Profile',function($http){
        return {
            getProfile: function(id){
                $http.get(httpUrl + 'vendors/detail?id=' + id).then(function(result){
                    return result.data;
                });
            }
        }
    })

And in controller I call Profile like so

.controller('profileCtrl', function($scope,$http,Profile){
        $scope.contact = function(id){
            $scope.vendor = Profile.getProfile(id);
            console.log($scope.vendor);
        }
}

But I always get undefined from the log. I'm expecting a json data returned from server. How can I do it correctly?

Upvotes: 0

Views: 451

Answers (4)

Shashank Vivek
Shashank Vivek

Reputation: 17514

The problem with your approach is that you are not handing the promise.

            $http.get(httpUrl + 'vendors/detail?id=' + id).then(function(result){
                return result.data;
            });

Here return result.data; is not a promise and so when you are handling it in controller, you are missing the response because its an asynchronous process (i.e. your data hasn't arrived from server yet) and so you get undefined .

factory.js

  .factory('Profile',function($http){
    return {
        getProfile: function(id){
            return $http.get(httpUrl + 'vendors/detail?id=' + id);
        }
    }
 })

in controller.js

   .controller('profileCtrl', function($scope,$http,Profile){
    $scope.contact = function(id){
        Profile.getProfile(id).then(function(response){
           $scope.vendor = response.data;
     });
        console.log($scope.vendor);
    }
 }

OR

USE this if you want to manipulate response before sending to controller

  .factory('Profile',function($http,$q){
    return {
        getProfile: function(id){ 
            var  deferred = $q.defer();
            $http.get(httpUrl + 'vendors/detail?id=' + id).then(function(resp){ 
                // modify the "resp" and then return
                deferred.resolve(resp);
            },function( error ){
              deferred.reject(error);
          })
        }
       return deferred.promise;
    }
 })

in controller.js

   .controller('profileCtrl', function($scope,$http,Profile){
    $scope.contact = function(id){
        Profile.getProfile(id).then(function(response){
           $scope.vendor = response;
     });
        console.log($scope.vendor);
    }
 }

Upvotes: 2

Giovani Vercauteren
Giovani Vercauteren

Reputation: 1908

Your factory method getProfile() doesn't return anything. The return inside the .then() of the $http.get returns that value to be used in the next .then().

The best option is to return the entire $http call. Like so:

getProfile: function(id){
    return $http.get(httpUrl + 'vendors/detail?id=' + id).then(function(result){
        return result.data;
    });
}

You can keep the return inside, so that the next .then() you do will already have the correct parameters, without needing to do "result.data". Like so:

.controller('profileCtrl', function($scope,$http,Profile){
    $scope.contact = function(id){
        Profile.getProfile(id).then(function(response) {
            $scope.vendor = response;
            console.log($scope.vendor);
        });
    }
}

A $http call returns a promise which can be chained on. Everything you return inside a promise can be used in the next chain. more info

Upvotes: 1

Nizardinho
Nizardinho

Reputation: 80

i think you missing close your parentheses and maybe in your factory too, you need to call factory like this :

.controller('profileCtrl', ['$scope','$http','Profile',  
  function($scope,$http,Profile){
    $scope.contact = function(id){
        $scope.vendor = Profile.getProfile(id);
        console.log($scope.vendor);
    }
}]);

Hope this help

Upvotes: 0

manish
manish

Reputation: 1458

there's slight problem with the your code. By the time your Profile.getProfile(id) initializes $scope.vendor the console.log($scope.vendor); has already been executed, which is why you get undefined

what you want to do is console.log($scope.vendor); in the then of your factory. Something like:-

Profile.getProfile(id) 
.then(function(response){ 
   $scope.vendor = response.data.value;
   console.log($scope.vendor);
});

Upvotes: 0

Related Questions