为什么Angular $资源返回一个Resource对象而不是类对象?

时间:2015-03-01 16:02:17

标签: angularjs coffeescript

使用CoffeeScript,Angular和$ resource,我创建了以下工厂:

angular.module('myapp', ['ngResource']).factory 'MyObject', ['$resource', ($resource) ->
    MyObjectResource = $resource '/api/my_object/:id', {
      id: '@id'
    }, {
      update:
        method: 'PUT'
    }

    class MyObject extends MyObjectResource

      someMethod: ->
        dosomething
 ]

问题在于,当我从API加载对象时,我得到一个Resource对象而不是MyObject对象,这是一个问题,因为我无法访问其他对象方法

以下是获取对象的代码:

result = MyObject.get({id: 1})

如果我打印result,我可以看到:

Resource {id: 1, details: 'somestuff'}

相比之下,我希望有:

MyObject {id: 1, details: 'somestuff'}

这将使我能够访问someMethod以及我为此类定义的所有其他方法。

我做错了吗?

提前致谢。

1 个答案:

答案 0 :(得分:5)

在快速查看源代码后,我看到以下关系:

  1. 在工厂内创建了Resource函数($resource提供程序),并在调用$resource时返回。
  2. 资源具有以下结构(让我们想象一下,我们只想了解它所拥有的方法的高级视图,而不是每种方法的工作方式)

    function Resource(value) { ... }
    Resource.prototype.toJSON = function () { ... }
    Resource.prototype.bind = function () { ... }
    
    1. 我还看到$resource函数在第3个参数中接收到要在Resource函数上设置的其他操作(与某些默认操作合并),我看到你是'发送额外的update方法,因此该对象具有以下结构
    2. update与默认操作合并:

      {
        'get': {method: 'GET'},
        'save': {method: 'POST'},
        'query': {method: 'GET', isArray: true},
        'remove': {method: 'DELETE'},
        'delete': {method: 'DELETE'},
        // added by the user
        update: { method: 'PUT' }
      }
      

      $resourceResource函数的此哈希的每个属性设置一个方法,并在方法名称前附加Resource $的原型设置方法,即< / p>

      Resource.get = function () { ... }
      Resource.save = function () { ... }
      Resource.update = function () { ... }
      ...
      
      Resource.prototype.$get = function () { ... }
      Resource.prototype.$save = function () { ... }
      Resource.prototype.$update = function () { ... }
      ...
      

      现在返回到您的代码,您需要从MyObject扩展新功能MyObjectResource,其中MyObjectResource是调用$resource的结果,即Resource在上面看到的函数中,coffeescript的extend实际上会将MyObjectResource上定义的所有属性复制到MyObject,并且还会隐藏[[Prototype]]属性MyObject.prototype指向MyObjectResource.prototype

      MyObjectResource                
        prototype     ------->  MyObjectResource.prototype
                                  $get
        get                       $save
        save                      toJSON
        ...                       ...
                                   ^
                                   |
      MyObject                     |
        prototype     ------->  MyObject.prototype
        get (reference)           someMethod
        set (reference)
        ...
      

      这就是为什么你可以执行MyObject.get的原因,因为它现在引用了MyObjectResource.get,即MyObject.get === MyObjectResource.get

      这是有趣的部分,调用MyObject.get将返回MyObjectResrouce的实例(这实际上已经被编码,但只有当MyObject.get this内部没有时才会发生MyObjectResource Source的实例,如果我们new MyObjectResource()无法访问someMethod,因为它实际上是在&#34中定义的;子&#34;

      但是我们可以创建MyObject的实例,并且由于coffeescript extend创建的链接,实例可以访问相同的getMyObjectResource.prototype.$get ,所以:

      var instance = new MyObject()
      instance.$get({id: 1});     // works because of the link created between the prototypes
      instance.someMethod();      // also works