【问题标题】:AngularJS: $resource with nested resourcesAngularJS:具有嵌套资源的 $resource
【发布时间】:2014-11-14 10:52:51
【问题描述】:

我正在将 AngularJS $resource 模型用于 REST API。我有这样的东西:

angular.module('libraryapp')
    .factory('Book', function($resource){
        return $resource('books/:id');
    });

我是这样使用的:

Book.get({ id: 42 }, function(book) {
    console.log(book);
});

但我也想要一个子资源的端点,比如说:

GET /books/:id/comments

我应该如何在模块中定义它?我可以以某种方式扩展 Book,像这样使用它

Book.get({ id: 42 }).Comment.query(function(comments) {
    console.log(comments);
});

【问题讨论】:

    标签: angularjs rest restful-url


    【解决方案1】:

    您可以使用 AngularJS $resource 定义轻松访问嵌套的 RESTful 资源。

    线索是了解$resource 定义中每个action 定义(在actions 列表中)的params 参数如何工作。正如文档所说,这是一个

    此操作的可选预绑定参数集。 […]

    angular.module('libraryApp').factory('Book', [
      '$resource', function($resource) {
        return $resource('books/:id/:subResource', {}, {
          comments: {  // The `comments` action definition:
            params: {subResource: 'comments'},
            method: 'GET'
          }
        });
      }
    ]);
    

    鉴于上述定义,您应该仍然可以像以前一样使用Book。例如Book.get({ id: 42 }) 转换为GET books/42/ 请求。

    但是,鉴于 $resource URL ('books/:id/:subResource') 的新 :subResource 部分,您现在可以生成一个

    GET books/42/comments
    

    通过调用 either Book.get({ id: 42, subResource: 'comments' }) 或定义为您的 comments 操作的更简洁优雅的界面 Book.comments({ id: 42 }) 来请求。

    【讨论】:

    • 我知道我回答得这么晚了,但是如果答案对你有用,那么如果你接受它作为答案会很棒——这样其他用户就可以从知道答案有效的过程中受益。如果您有任何问题,请告诉我。
    • 这个解决方案的问题是返回的 cmets 将是 Book 资源的实例。所以如果我们调用Book.comments({ id: 42 }).$promise.then(function (comments) { comments[0].$get(); }); 那么这个$get 会尝试调用GET /books/<commend_id> 这当然是不对的。
    • djxak,你有解决这个问题的方法吗?
    【解决方案2】:

    据我所知,你不能嵌套资源,但是做你正在寻找的东西非常简单:

    您可以定义可以在每个资源中覆盖的可选参数(如 category 此处),甚至覆盖 url(查看 otherUrl 资源)

    angular.module('libraryApp').factory('Book', [
      '$resource', function($resource) {
        return $resource('books/:id/:category', {}, {
          comments: {
            method: 'GET',
            action: 'category'
          },
          otherUrls: {
            method: 'GET',
            url: 'books/:id/admin/:option'
          }
        });
      }
    ]);
    

    【讨论】:

      【解决方案3】:

      您可能希望使用 Restangular,因为它可以处理嵌套资源并且是一种干净且简单的方法。

      【讨论】:

        【解决方案4】:

        正如 djxak 所指出的,向资源添加动作意味着返回值是包含资源类型,而不是子资源类型。

        我通过使用子资源 URL 创建新资源并修改包含资源的原型以添加功能解决了类似的问题:

        angular.module('libraryapp')
            .factory('Book', function($resource){
                var bookUrl = 'books/:id',
                    Book = $resource(bookUrl),
                    BookComment = $resource(bookUrl + /comments");
        
                Book.prototype.getComments = function () {
                    return BookComment.query({id: this.id});
                };
        
                return $resource('books/:id');
            });
        

        那么用法就变成了:

        Book.get({ id: 42 }).getComments(function(comments) {
            console.log(comments);
        });
        

        我看到这种方法的唯一缺点是,如果您有一个通过不同 URL 访问的单独的“评论”资源,则必须为替代端点复制 $resource 初始化代码。不过,这似乎有点不便。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-07-21
          • 1970-01-01
          • 2011-08-23
          • 2014-08-02
          • 1970-01-01
          • 2012-04-21
          • 1970-01-01
          相关资源
          最近更新 更多