Backbone.js & REST API resources relationship & in

2019-07-23 14:22发布

问题:

I have a small REST API that is being consumed by a single page web application powered by Backbone.js

There are two resource types that the API provides, and therefore, the Backbone app uses. These are articles and comments. These two resources have different endpoints and there is a link from each of the articles to the location of all the comments for that item.

The problem that I'm facing is that, on the article list in my web app I would like to be able to display the number of comments for each article. Given that that would only be possible if I also get the comments list, on the current setup, would require me to make one API request to get the the initial article list and another one for each of the articles to be able to count the number of comments. That becomes a problem if, for instance, there are 100 articles, and therefore 101 HTTP requests would be necessary to populate one single view.

The solutions I can think of right now are:

1. to include the comments data in the initial articles request like so

{
  {
    "id": 1,
    "name": "Article 1",
    ...
    "comments": {
      {
        "id": 1,
        "text": "some comment"
      },
      {
        "id": 2,
        "text": "some comment"
      },
      ...
    }
  },
}

The question in this case is: How is it possible to parse the "comments" as a separate comments collection and not include it into the article model?

2. to include some metadata inside the articles response like so:

{
  {
    "id": 1,
    "name": "Article 1",
    ...
    "comments": 13
  },
}

Option that raises the question: how should I handle the parse of the model so that, on one hand the meta information is available, and on the other hand, the "comments" attribute is not one Backbone would try to perform updates on?

I feel there might be another solution, compliant with the REST philosophy, for this that I'm missing, so if you have any other suggestion please let me know.

回答1:

I think your best bet is to go with your second option, include the number of comments for each article inside your article model.

Option that raises the question: how should I handle the parse of the model so that, on one hand the meta information is available, and on the other hand, the "comments" attribute is not one Backbone would try to perform updates on?

Not sure what your concern is here. Why would you be worried about the comments attribute getting updated?

I can't think of any other "RESTy" way of achieving your desired result.



回答2:

I would suggest using alternative 2 and have the server return a subset of the article attributes that are deemed useful for applications when dealing with the article collection resource (perhaps reachable at /articles).

The full article member resource with all its comments (whether they are stored in separate tables in the backend) would be available at /articles/:id).

From a Backbone.js point of view you probably want to put the collection resource in a, say, ArticleCollection which will convert each member (currently with a subset of the attributes) to Article models.

When the user selects to view an article in full you pull it out from the ArticleCollection and invoke fetch to populate it in full.

Regarding what to do with extra/virtual attributes that are included in the collection resource (/articles) like the comment count and possibly other usefult aggregations, I see a few alternatives:

  1. In Article#initialize you can pull those out from the attributes and store them as meta-data on the article. This way the built-in Backbone.Model#toJSON will not see them.
  2. Keep them in the attributes section of each model and override Backbone.Model#toJSON to exlcude them when "serializing" an Article.

In atlernative 1, an Article#commentCount() helper could return this._commentCount || this.get('comments').length to make it work on both partially and fully loaded articles.

For a fully loaded Article you would probably want to convert the nested comments array into a full-blown CommentCollection anyway and store that in this._comments so I don't think it is that unusual to have your models store additional stuff directly on the model instance, outside of its attributes hash.