-1

I am willing to get a value from $http service in AngularJS and set it inside $scope.listing. Because this is asynchronous action $scope.listing is empty when the page is loaded. I saw some implementations using promise and factory in order to solve it but it feels like an overkill to me. Is there an elegant way to do it?

It looks like that:

$http.get('/getlisting/')
.success(function(response) {
            $scope.listing = response;
    })
console.log ($scope.listing) // is empty
guyyug
  • 897
  • 1
  • 11
  • 23
  • 1
    Move the console.log statement inside the success handler. That actually gets called when the promise is resolved. It's not overkill, it's how asynchronous "stuff" works – Amy Blankenship Dec 29 '15 at 16:11
  • No way of getting around the promise since the $http API is based on the deferred/promise APIs exposed by the $q service. As far as where to make the call, doing it in a service, especially if data is used in more than one controller, is the generally accepted approach. Additionally, .success has been deprecated in favor of .then – jbrown Dec 29 '15 at 16:13
  • Please narrow a bit your question. btw, the view is compiled before the controller is run, so, unless you go deeply into angular, you won't be able to display your view with data initialized. – Deblaton Jean-Philippe Dec 29 '15 at 16:14

3 Answers3

1

change code like below

$http.get('/getlisting/')
.success(function(response) {
        $scope.listing = response;
        console.log ($scope.listing) // is empty
})

your current console.log is getting executed even before the response has come from the server, hence it is not printing anything... if you move it inside .success you will see the value being printed to console

harishr
  • 17,807
  • 9
  • 78
  • 125
  • Yes. The code is already as simple, clear, and "elegant" as it gets. It's already using a promise with the .success handler, so no need to add another one. There really isn't anything you can do that would make it more elegant. – Mohair Dec 29 '15 at 16:29
  • Of course moving the console.log to the .success will solve the problem but I need it outside the .success. I just wrote it there to visualize the issue. – guyyug Dec 29 '15 at 20:11
0

If you want $scope.listing to be populated by the time the user arrives at that specific page, you can leverage ui-router's resolve. You are basically telling the router not to allow the user to go to that page until the requested data (listing) has been returned from your $http call.

See: http://www.jvandemo.com/how-to-resolve-angularjs-resources-with-ui-router/

Henry Zou
  • 1,809
  • 1
  • 14
  • 19
-1

Always use services and primises to handle http calls.

angular.module('App').factory('Request',['$q','$http',function($q,$http){
  return {
    send : function(conf){
      var defer = $q.defer();  
      $http(conf).success(function(response) {
          defer.resolve(response);
      }).error(function(err){
          defer.reject(err);
      });
      return defer.promise;
    }
  };
}])

and in your controller

angular.module('App').controller('MainCtrl',['$scope','Request',function($scope,Request){
 var conf = {
   url : 'some url',
   method : 'GET/POST/PUT/DELETE etc...',
   data : {some : 'data'}
 }; 

 Request.send(conf).then(function(response){
    // todo handle success response here 
 }).catch(function(err){
    // todo handle http error here
 });
}]);
Ashot
  • 1,229
  • 1
  • 12
  • 13
  • @georgeawg antipatern ? Could you please specify what is incorrect in the code above ? – Ashot Dec 29 '15 at 18:11
  • sure, but doing so we write http construct only once .It is just wrapper for http service. What is wrong ? Writing wrappers ? – Ashot Dec 29 '15 at 18:15
  • In addition the `.success` and `.error` methods are deprecated. See the deprecation notice -- https://docs.angularjs.org/api/ng/service/$http#deprecation-notice – georgeawg Dec 29 '15 at 18:17