6

我有一个从查询中返回数组的资源,如下所示:

.factory('Books', function($resource){
    var Books = $resource('/authors/:authorId/books');
    return Books;
})

是否可以将原型方法添加到从此查询返回的数组中?(注意,不是array.prototype)。

例如,我想将方法​​添加hasBookWithTitle(title)到集合中。

4

3 回答 3

5

ricick 的建议是一个很好的建议,但是如果您想在返回的数组上实际拥有一个方法,那么您将很难做到这一点。基本上,您需要做的是围绕 $resource 及其实例创建一些包装器。您遇到的问题是 angular-resource.js 中的这行代码:

var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data));

这是设置 $resource 的返回值的地方。发生的情况是在执行 ajax 请求时填充并返回“值”。当 ajax 请求完成时,该值返回到上面的“值”中,但通过引用(使用 angular.copy() 方法)。数组的每个元素(对于像 query() 这样的方法)都是您正在操作的资源的一个实例。

因此,您可以扩展此功能的一种方法是这样的(未经测试的代码,因此如果不进行一些调整可能无法工作):

var myModule = angular.module('myModule', ['ngResource']);
myModule.factory('Book', function($resource) {
    var service = $resource('/authors/:authorId/books'),
        origQuery = service.prototype.$query;

    service.prototype.$query = function (a1, a2, a3) {
        var returnData = origQuery.call(this, a1, a2, a3);
        returnData.myCustomMethod = function () {
            // Create your custom method here...
        return returnData;
        }
    }

    return service;
});

同样,您将不得不稍微弄乱它,但这是基本思想。

于 2013-03-08T03:46:03.367 回答
4

这可能是创建自定义服务扩展资源并向其添加实用程序方法的好案例,而不是向默认资源服务的返回值添加方法。

var myModule = angular.module('myModule', []);
myModule.factory('Book', function() {
    var service = $resource('/authors/:authorId/books');
    service.hasBookWithTitle = function(books, title){
        //blah blah return true false etc.
    }
    return service;
});

然后

books = Book.list(function(){
    //check in the on complete method
    var hasBook = Book.hasBookWithTitle(books, 'someTitle');
})
于 2013-03-08T00:28:05.657 回答
2

查看 angular-resource.js 中的代码(至少对于 1.0.x 系列),您似乎无法为任何类型的默认行为添加回调(这对我来说似乎是正确的设计)。

如果您只是在单个控制器中使用该值,则可以在调用query资源时传入回调:

var books = Book.query(function(data) {
    data.hasBookWithTitle = function (title) { ... };
]);

或者,您可以创建一个服务来装饰 Books 资源,将所有调用转发到 get/query/save/etc.,并使用您的方法装饰数组。示例在这里:http://plnkr.co/edit/NJkPcsuraxesyhxlJ8lg

app.factory("Books",
  function ($resource) {
    var self = this;
    var resource = $resource("sample.json");

    return {
      get: function(id) { return resource.get(id); },
      // implement whatever else you need, save, delete etc.
      query: function() {
        return resource.query(
          function(data) { // success callback
            data.hasBookWithTitle = function(title) {
              for (var i = 0; i < data.length; i++) { 
                if (title === data[i].title) {
                  return true;
                }
              }
              return false;
            };
          },
          function(data, response) { /* optional error callback */}
        );
      }
    };
  }
);

第三,我认为这更好,但这取决于您的要求,您可以采用功能方法并将 hasBookWithTitle 功能放在您的控制器上,或者如果需要共享逻辑,则在实用程序服务中。

于 2013-03-08T19:02:53.650 回答