1

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 !

5 Answers 5

1

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

Sign up to request clarification or add additional context in comments.

Comments

0
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.

2 Comments

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 ... :-/
This will solve that issue as well. Replace your code where the '...' is.
0

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);
});

Comments

-1

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();

2 Comments

You have way too many returns in your code. This will not work.
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.
-2

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;
    });
};

1 Comment

This will return an empty array, the call to ObjectFactory is async.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.