user1361529
user1361529

Reputation: 2697

AngularJS promise handling with http

here is a piece of code I am struggling with - I have a controller (zmApp.MonitorCtrl) that is calling a factory (ZMFactory) with an HTTP request.

The problem I am facing is this: a) When the controller calls ZMFactory.getMonitors() it returns undef and I get an error ERROR: Error: undefined is not an object (evaluating 'ZMFactory.getMonitors().then')

b) After this error comes up, the http request in the factory is processed

I am a little confused. Can you please check if the factory has been set up correctly to return a promise?

var app = angular.module('zmApp.controllers');

app.controller('zmApp.MonitorCtrl',  function($ionicPlatform, $scope,$http,ZMFactory)
{
            
            $scope.monitors=[];
            console.log("***CALLING FACTORY");
            ZMFactory.getMonitors().then(function(data)
            {
               $scope.monitors = data;
               console.log ("I GOT " +$scope.monitors);
            });
               
});



app.factory('ZMFactory',['$http', '$rootScope',function($http,$rootScope)
{
    //var factory = {};
    var monitors =[];
    return {
        getMonitors: function()
        {
            console.log("***MAKING REQUEST");
            $http({
                    url:'http://myurl.com:9999/zm/index.php?skin=xml',
                    method:'post',
                    headers: {'Content-Type': 'application/x-www-form-urlencoded',
                               'Accept': '*/*',
                               },
                        transformRequest: function(obj) {
                               var str = [];
                               for(var p in obj)
                               str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
                               var foo= str.join("&");
                               console.log ("****RETURNING "+foo);
                               return foo;
                        },
                        transformResponse: function(data)
                        {
                            var x2js = new X2JS();
                            var json = x2js.xml_str2json(data);
                            console.log ("***Transmogrifying XML to JSON");
                            return json;
                        },
                        data: {username:'xxx',
                               password:'xxxx',
                               action:'login',
                               view:'console'}
                               
                      }) //http
                      .success (function(data)
                      {
                          console.log("****YAY"+JSON.stringify(data));
                                   
                          var subobj =data.ZM_XML.MONITOR_LIST.MONITOR;
                          var len = subobj.length;
                          for (var i =0; i< len; i++)
                          {
                           console.log ("HERE " + subobj[i].NAME);
                           monitors.push(subobj[i]);
                           }
                          // $rootScope.$broadcast ('handleZoneMinderMonitorsUpdate',monitors);
                           return monitors;
                        }) //success
                        .error(function(data, status, headers, config)
                        {
                           console.log("***OOPS "+status + " H: "+data);
                           return monitors;
                        });

        } //getMonitors
    };//return
    console.log ("**** NEVER *****");
                        
}]);

Upvotes: 0

Views: 185

Answers (2)

New Dev
New Dev

Reputation: 49590

The key to the answer is in the wording of your own question:

Can you please check if the factory has been set up correctly to return a promise

You need to return it. Right now your getMonitors function (if I remove all the code irrelevant to the question) is as follows:

getMonitors: function(){
  $http({})
    .success(function(data){
       // convert data to monitors
       return monitors;
    });
}

This is a function call that doesn't return anything, or rather, returns undefined. There is no "magic" with promises - it's just as any other object - you need to return it to the caller.

So, two things you need to do:

1) Change from .success to .then. .then generates a new chained promise that delivers, when returned, the monitors to the consumer (that you are returning in the .then handler). On the other hand, .success returns the original promise (generated by $http) and data returning from .success is lost.

2) Actually return the $http call (or, rather, $http().then() call)

Here's conceptually how this would look like:

app.factory('ZMService', function ZMServiceFactory($http){
    return {
        // getMonitors function of the ZMService service
        getMonitors: function(){
          return $http({})
            .then(function(response){
               var data = response.data;
               // convert data to monitors
               return monitors;
            });
        }
    };
});

(also, noticed how I renamed your service from ZMFactory to ZMService. A "factory" in the name is a misnomer. The factory is the function that generates the instance - hence "the factory" - but the instance itself is an object, which is called a "service" in Angular)

Upvotes: 1

Pranay Dutta
Pranay Dutta

Reputation: 2591

try with this,here i am returning the promise as is

var app = angular.module('zmApp.controllers');

app.controller('zmApp.MonitorCtrl',  function($ionicPlatform, $scope,$http,ZMFactory)
{

            $scope.monitors=[];
            console.log("***CALLING FACTORY");
            ZMFactory.getMonitors().then(function(data)
            {
               $scope.monitors = data;
               console.log ("I GOT " +$scope.monitors);
            });

});



app.factory('ZMFactory',['$http', '$rootScope',function($http,$rootScope)
{
    //var factory = {};
    var monitors =[];
    return {
        getMonitors: function()
        {

          return  $http({
                    url:'http://myurl.com:9999/zm/index.php?skin=xml',
                    method:'post',
                    headers: {'Content-Type': 'application/x-www-form-urlencoded',
                               'Accept': '*/*',
                               },
                        transformRequest: function(obj) {
                               var str = [];
                               for(var p in obj)
                               str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
                               var foo= str.join("&");
                               console.log ("****RETURNING "+foo);
                               return foo;
                        },
                        transformResponse: function(data)
                        {
                            var x2js = new X2JS();
                            var json = x2js.xml_str2json(data);
                            console.log ("***Transmogrifying XML to JSON");
                            return json;
                        },
                        data: {username:'xxx',
                               password:'xxxx',
                               action:'login',
                               view:'console'}

                      }) //http
                      .then(function(data)
                      {
                          console.log("****YAY"+JSON.stringify(data));

                          var subobj =data.ZM_XML.MONITOR_LIST.MONITOR;
                          var len = subobj.length;
                          for (var i =0; i< len; i++)
                          {
                           console.log ("HERE " + subobj[i].NAME);
                           monitors.push(subobj[i]);
                           }
                          // $rootScope.$broadcast ('handleZoneMinderMonitorsUpdate',monitors);
                           return monitors;
                        },function(error)
                        {

                           return error;
                        });

        }
    };

}]);

Upvotes: 1

Related Questions