Boris Zagoruiko
Boris Zagoruiko

Reputation: 13174

Angular.js resourceProvider returns $promise with data

Given angular.js service:

angular.module('mymodule').factory('Products', ['$resource',
    function($resource) {
        return $resource('/path/to/getProducts', {}, {
            find: {
                method: 'GET',
                isArray: false
            }
        });
    }
]);

In the controller of mymodule I make find query:

$scope.findAll = function () {
    Products.find(function (products) {
        console.log(Object.keys(products));
        // ['prodA', 'prodB', ... , '$promise', '$resolved']
        for (var i in products) {
            if (!products.hasOwnProperty(i)) continue;
            console.log(products[i].description.someprop);
            // Got error: Cannot read property 'someprop' of undefined
            // Trust me: I debug this place. someprop is defined for all items except that two
        }
    });
};

It works fine but returns $promise and $resolved with data set, so that I can not loop through my data.

Angular documentations says that the Resource instances and collection has these additional properties. But I don't understand exactly how to control it in my code.

What am I doing wrong? How to prevent it?

Upvotes: 3

Views: 1723

Answers (4)

bcsshdha
bcsshdha

Reputation: 129

Try doing response.toJSON and it returns just your json excluding promise and resolve.

data.$promise.then(function(myResponse) {
    var actualData = myResponse.toJSON();
}

Upvotes: 0

deonclem
deonclem

Reputation: 880

Indeed it's a bit more complicated when you're not working with arrays.

The response object sent back from the server contains:

  • the resource object (your data + $promise and $resolved, that's what you get in your callback)
  • a config object (the headers, the method used, the url called, etc) and a headers function
  • and a data object, that's what we want ! It contains just the data.

But you will only get to see response.resource in your then(). You therefore need to intercept the response sent by the server to get the data instead:

return $resource('/path/to/getProducts', {}, {
        find: {
           method: 'GET',
           isArray: false,
           interceptor: {
             response: function(response) {  
               return response.data;
             }
           }
        }
    });

And then in your controller :

Products.find().$promise.then(
    function(products){
        angular.forEach(products, function(value, index){
            console.log(value);
        });
    }
);

Tell me if this works for you.

Plunker Demo

Upvotes: 8

Petr Averyanov
Petr Averyanov

Reputation: 9486

I guess your problem is 'isArray: false'. So your products is not an array, but object. Set 'isArray: true' and you can iterate for(var product in products) all day.

Upvotes: 0

Ben Fortune
Ben Fortune

Reputation: 32137

Resources return a promise, you can retrieve the data from the promise using then().

Products.find().$promise.then(function (products) {
    console.log(Object.keys(products));
});

Upvotes: 0

Related Questions