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

tho*_*phn 4 coffeescript angularjs

使用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
 ]
Run Code Online (Sandbox Code Playgroud)

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

这是我获取对象的代码:

result = MyObject.get({id: 1})
Run Code Online (Sandbox Code Playgroud)

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

Resource {id: 1, details: 'somestuff'}
Run Code Online (Sandbox Code Playgroud)

相比之下,我希望有:

MyObject {id: 1, details: 'somestuff'}
Run Code Online (Sandbox Code Playgroud)

这将使我能够访问someMethod我为此课程定义的所有其他方法.

难道我做错了什么?

提前致谢.

Mau*_*ppe 5

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

  1. Resource在工厂内部(它是$resource提供者)创建了一个函数,并在$resource调用时返回.

资源具有以下结构(让我们想象一下,我们只想获得它所拥有的方法的高级视图,而不是每个方法的工作方式)

function Resource(value) { ... }
Resource.prototype.toJSON = function () { ... }
Resource.prototype.bind = function () { ... }
Run Code Online (Sandbox Code Playgroud)
  1. 我还看到$resource函数在第3个参数中接收要在函数上设置的附加动作(与某些默认动作合并)Resource,我看到你正在发送一个额外的update方法,所以该对象具有以下结构

合并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' }
}
Run Code Online (Sandbox Code Playgroud)

$resourceResource函数上的这个散列的每个属性设置一个方法,也Resource$在方法名称之前附加a 的原型设置一个方法,即

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

Resource.prototype.$get = function () { ... }
Resource.prototype.$save = function () { ... }
Resource.prototype.$update = function () { ... }
...
Run Code Online (Sandbox Code Playgroud)

现在回到你的代码中正在延伸的新功能MyObjectMyObjectResource哪里MyObjectResource是调用的结果,$resource也就是Resource上面看到,CoffeeScript中的功能extend实际上将复制上定义的所有属性MyObjectResourceMyObject,也使隐藏[[Prototype]]的属性MyObject.prototypeMyObjectResource.prototype:

MyObjectResource                
  prototype     ------->  MyObjectResource.prototype
                            $get
  get                       $save
  save                      toJSON
  ...                       ...
                             ^
                             |
MyObject                     |
  prototype     ------->  MyObject.prototype
  get (reference)           someMethod
  set (reference)
  ...
Run Code Online (Sandbox Code Playgroud)

所以这就是你可以做的MyObject.get原因,因为它现在有一个参考MyObjectResource.get,即MyObject.get === MyObjectResource.get

这是有趣的部分,调用MyObject.get将返回一个实例MyObjectResrouce(这实际上是被编码的,但只有在内部MyObject.get this不是MyObjectResource Source的实例时才会发生),如果我们这样做new MyObjectResource()是无法访问的,someMethod因为它实际上是在"子类"中定义的.

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

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