0

I have a DB with a collection of games and a collection of comments about those games. each game has a unique ID and each comment has a field game_id.

in the client side, I wrote an async function in the scope that retrieves the number of comments for a game from the db and return a promise. what is the right (and most cleanest) way to show the value in the HTML ?

I know there are different ways to do this. I am looking for the simplest and cleanest way.

Will this code work?

//code in HTML
<div ng-repeat="game in games">
<span>{{game.date}}</span>
<span>{{game.home}}</span>
<span>{{game.away}}</span>
<span>{{getNumberOfComments(game.id)}} Comments</span>  
</div>

app.factory('apiService', function($http) {
  return {
    getGames: function() {
      return $http.get('/api/games',{cache: true});
    },
   getCommentsCount: function(game_id) {
      return $http.get('/api/CommentsCount/' + id);
    }
  };
});

app.controller('MyCtrl', function ($scope, apiService) {
  gameService.getGames().then(function(resp) {
        $scope.games = resp.data;
  });

 $scope.getNumberOfComments = function(id){ 
     return apiService.getCommentsCount(id).then(function(resp){
       return resp.data;
  });
 });
});

Followup question: if I have many games (lets say 30), is it a bad idea to send 30 HTTP requests to the server for each game? is it better to send one request called "getAllComments" and retrieve the comments count for each game from the repsonse ?

for example:

function getAllComments() {
   $http.get('/allComments',function(data){
       $scope.games.forEach(function(game){
           game.commentsCount = data[game.id];
       });
   });
}

 //code in HTML
<div ng-repeat="game in games">
<span>{{game.commentsCount}} Comments</span>  
</div>

This seems like a good solution - but the problem starts when i have more than 30 games but i want to show 30 games to the user and give him the possibility to load more. Then im actually asking more comments than I need and i have to run this function every time the user loads more games. it seems like a complicated and efficient solution.

EDIT:

One solution is to aggregate the information on the server side and have the client send 1 HTTP request and the response will include all the information. To implement this I will need to iterate the list of games in the server side and for each game retrieve the comments count from the comment collection. The downside of this solution is that the it will take longer for the client to see the list of games. I rather the client to first see the list of games as soon as possible and then after that to load the number of comments. Another downside is the in NodeJS (the backend framework that I'm using), a code like that will block the main thread from serving other clients. Therefore I do not want to make any iterations on the server side.

One more thing that needs to take into account is caching. I want to save the HTTP request that retrieves the games in the $http cache. Because the list of games is static and not going to change, unlike the comments count, that is always increasing. This way when the client moves to a different route and comes back to the games list, the games will show up immediately. But I do want to load the comments count every time the user comes back to the games page.

2
  • 1
    If possible, I recommend returning the comment count in your games data from the api in order to avoid additional round trips to the server? Commented Jul 13, 2016 at 15:14
  • Do you mean - whenever I'm adding a new comment in the server, I should increase the comment count on the game document? It is possible, but then i cant cache the games request. I want to be able to cache the http request for the games. because the data in the games collection is static and not going to change. On the other hand, I want the comments count to be updated when the user returns to the games page. Commented Jul 13, 2016 at 15:27

1 Answer 1

1

A clean way to do this would be to first move the code that makes the http call to a service:

app.factory('gameService', function($http) {
  return {
    getGames: function() {
      return $http.get('/api/games');
    }
  };
});

Then, inject the service in your controller, call the get method and set the value on scope to be used by the view:

app.controller('MyCtrl', function ($scope, gameService) {
  $scope.model = {};
  gameService.getGames().then(function(resp) {
    $scope.model.games = resp.data;
  });
});

And your html would be like this:

<div ng-repeat="game in model.games">
  <span>{{game.comments.length}} Comments</span>  
</div>

Note that this assumes that the endpoint returns all the games and each game has a field for the comments. For example, the schema for a Game might look like this:

{
  "id": "1",
  "name": "The best game",
  "comments": [
    {
      "id": "c1",
      "content": "The is the best game ever"
    }
  ]
}
Sign up to request clarification or add additional context in comments.

3 Comments

Sorry for not explaining myself - but the collection of the games and the collection of the comments in the DB are separated. It is separated because i want to be able to find a comment by ID and to be able to index comments. There is a "games" collection and a Comments collection. each game has an ID field and each comment has an game_ID field.
Can you create an endpoint in your backend to aggregate the two so that the client can make one call and get what it needs to display ?
Do you think its a better solution? To implement this logic I will have to iterate the games in the server. and for each game, I need to retrieve the information about the game from the comments collection. From what I understood about NodeJS (the backend framework that im using) you should not write this type of code. because it blocks the main Thread from serving other clients. in addition, I rather the client to first see the list of games ASAP, and then wait another couple of seconds to see the comments count. You know what I mean ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.