2

I found very strange behavior of Angular $resource. Please checkout following lines of code:

    class Service
        constructor: ($resource) ->
            service = $resource '/record/:id'

            Service::list = (cb) ->
                service.query().$promise.then (data) ->
                    #result: data == [e, $promise: Object, $resolved: true]
                    cb data

            Service::get = (id, cb) ->
                service.get(id:id).$promise.then (data) ->
                    #result: data == {id: 1, name: 'name' ...}
                    cb format data

Service "get" method returns correct value (object) sent by server, but the "list" method as result return array which contains $promise and $resolved...

Does anyone has some logic explanation?

UPDATE:

I found the problem. Service result is array of strings and that cause as result array of sting chars. This can be solved by using $http instead of $resource.

Ex:

server-side -> ['list', 'of', 'elements']

client-side -> ['l','i','s','t']

ikamatovic
  • 43
  • 2
  • 7

3 Answers3

5

If like me you'd like your response to give you the data without the extra $promise and $resolved attributes you can modify the resource and add an 'interceptor' as described here: http://docs.angularjs.org/guide/migration#resource-promises-are-resolved-with-the-resource-instance

For a get it will look like this:

var Resource = $resource('/url', {}, {
  get: {
    method: 'get',
    interceptor: {
      response: function(response) {
        // expose response
        return response;
      }
    }
  }
});

Then you can access the response object rather than the resource instance when you make a get request. For example:

Resource.get(function(response){
    angular.forEach(response.data, function(value, key){

    }, $scope.varName);
});

This also means you can access other response attributes like response.status, response.headers as well as getting the instance of the resource with response.resource.

k0nG
  • 4,716
  • 2
  • 20
  • 18
2

but the "list" method as result return array which contains $promise and $resolved

Double check this--the way Chrome displays arrays inside a console.log when the array has extra properties is misleading. For example, try the following in the Chrome console:

> a = [1, 2, 3]

> a.$promise = 'thing'

> a.$resolved = true

> a
  [1, 2, 3]

> console.log(a)
  [1, 2, 3, $promise: "thing", $resolved: true]

As you can see, it lists $promise and $resolved as elements of the array, even though they're not actually in the Array.

Michelle Tilley
  • 157,729
  • 40
  • 374
  • 311
  • Hi Brandon. Thank you for helping and hint about Chrome inspector, but the problem is caused by response from server... – ikamatovic Sep 02 '13 at 16:25
  • Do you have any sources for why this is? It's VERY misleading when trying to debug responses. – coblr Jun 30 '15 at 20:47
0

The documentation itself mentions about this and it's usage

The Resource instances and collection have these additional properties:

$promise: the promise of the original server interaction that created this instance or collection.

On success, the promise is resolved with the same resource instance or collection object, updated with data from server. This makes it easy to use in resolve section of $routeProvider.when() to defer view rendering until the resource(s) are loaded.

On failure, the promise is resolved with the http response object, without the resource property.

$resolved: true after first server interaction is completed (either with success or rejection), false before that. Knowing if the Resource has been resolved is useful in data-binding.

Chandermani
  • 42,589
  • 12
  • 85
  • 88