Join the Stack Overflow Community
Stack Overflow is a community of 6.4 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

Hello everyone :) Here is the problem. I'm making an angular app with:

  • a factory to access to an api with $http that retrieves an array of objects from a server

    getObjectsFromApi : function(){
        return $http({
            url: 'http://path/to/the/api/',
            method: 'GET',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
            }
        })       
    },
    
  • and a service to compute retrieved data and inject it to controllers

    this.getObjectsFromService = function(){
        var objects = [];
    
        ObjectFactory.getObject()
        .success(function(data, status){
            console.log("Successfully got objects !");
            objects = data;
        })
        .error(function(data, status){
            console.log("Fail... :-(");
        });
    
        return objects;
    };
    

The problem is that when I return objects, it doesn't return any data. How can I do to return $http callback data within this getObjectsFromService function ?

Thank you for helping !

share|improve this question

You must use promises, something like this should do the trick

this.getObjectsFromService = function(){
    var defer = $q.defer();

    ObjectFactory.getObject()
    .then(function(data){
        console.log("Successfully got objects !");
        defer.resolve(data);
    })
    .catch(function(data){
        console.log("Fail... :-(");
         defer.reject(data);
    });

    return defer.promise;
};

And now you can use this function somewhere else like this:

var foo = function() {
    var objects = [];
    this.getObjectsFromService().then(function(data) {
        objects = data;
        //do rest of your manipulation of objects array here
    });
}

There is no other way to return the objects, it's not possible because $http is asynchronous. You'll have to rework the rest of the code and adapt it to this

share|improve this answer
var req = ObjectFactory.getObject();

req.success(function(data) {...}
req.error(function(data) {...}

This will do it for ya

The variable req will then be the promise sent back from the factory.

Edit

Keep in mind that your data will not be changes until the promise is resolved, so if you try to console.log(objects) before then, it will be empty.

share|improve this answer
    
I missed on my explanations: The problem is that I want to return data I got from the api in order to inject it in the controller. In other words, I want to get response data, put it into my "objects" variable and return this variable. So sorry for the bad english ... :-/ – user3405542 Feb 18 '15 at 16:17
    
This will solve that issue as well. Replace your code where the '...' is. – ribsies Feb 18 '15 at 17:07

The http request is async, which means that it completes after you return objects. Return the promise instead:

this.getObjectsFromService = function(){
    return ObjectFactory.getObject().catch(function(){
        console.log("Fail... :-(");
    });
}

Then

service.getObjectsFromService().then(function(resp) {
    console.log("Successfully got objects !", resp.data);
});
share|improve this answer

Your code is asynchronous. When you return objects, you return your initial empty array. You can't return directly your object, but instead you need to return a promise (see 3 possibilities below)

By creating a promise

var deferred = $q.defer();

ObjectFactory.getObjectsFromApi()
    .success(function(data, status){
        console.log("Successfully got objects !");
        // Do stuff and resolve promise
        deferred.resolve(data);
     })
     .error(function(data, status){
         console.log("Fail... :-("));
         // Do stuff and reject promise
         deferred.reject(data)
     });

return deferred.promise;

You can use promise chaining (use .then rather than .success and .error):
Note: when using then with success and error callbacks rather than success and error methods, you have only 1 argument which is the response object

return  ObjectFactory.getObjectsFromApi()
    .then(function(response){
        console.log("Successfully got objects !");
        // Do stuff and chain full response headers or data
        return responseHeaders;
        // or
        // return responseHeaders.data;
     }, function(responseHeaders){
         console.log("Fail... :-("));
         // Do stuff and chain error (full response headers or data)
         return $q.reject(responseHeaders)
         // return $q.reject(responseHeaders.data);
     });

Or if you have no business logic, or no reason to intervene in your factory, simply return your $http call directly:

return  ObjectFactory.getObjectsFromApi();
share|improve this answer
    
You have way too many returns in your code. This will not work. – ribsies Feb 18 '15 at 17:27
    
Yes, I had one return that I accidentally left, on the first example. The rest is correct. If you think there are too many returns, look at asynchronous programming ad promise chaining. – Thomas Roch Feb 19 '15 at 9:07

Angular $resource

Factory

getObjectsFromApi : function(){
    return $resource('http://path/to/the/api/', {}, 
    {
        get: {
            method: 'GET',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
            } 
        }
    })       
},

Service

this.getObjectsFromService = function(){
    var objects = [];

    ObjectFactory.get().$promise.then(function(data) {
         objects = data;
         return objects;
    }).error(function(err) {
        throw err;
    });
};
share|improve this answer
    
This will return an empty array, the call to ObjectFactory is async. – Thomas Roch Feb 18 '15 at 16:47

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.