5

私は2つのWebサービスを持っています:

次のように「Articles」を返します。

[   
    {
        "id": "1",
        "headline": "some text",
        "body": "some text",
        "authorId": "2"
    },
    {
        "id": "2",
        "headline": "some text",
        "body": "some text",
        "authorId": "1"
    }
]

そしてもう1つは、IDを指定すると、次のような「作成者」を返します。

{
    "id": "1",
    "name": "Test Name",
    "email": "test@test.com",
    "photo": "path/to/img"
}

この2つを組み合わせて、著者名と写真を記事概要リストに表示できるようにします。

このような:

[   
    {
        "id": "1",
        "headline": "some text",
        "body": "some text",
        "authorId": "2",
        "author_info": {
            "id": "2",
            "name": "Another Test Name",
            "email": "test2@test.com",
            "photo": "path/to/img"
        }
    },
    {
        "id": "2",
        "headline": "some text",
        "body": "some text",
        "authorId": "1"
        "author_info": {
            "id": "1",
            "name": "Test Name",
            "email": "test@test.com",
            "photo": "path/to/img"
        }
    }
]

記事をフェッチする「Articles」サービスがありますが、「Articles」サービスの出力を返す前に、同様の「Authors」サービスからの著者情報で返されたJSONを強化するための最良のアプローチは何ですか?

factory('Authors', ['$http', function($http){
    var Authors = {

        data: {},

        get: function(id){
            return $http.get('/api/authors/' + id + '.json')
                .success(function(data) {
                    Authors.data = data;
                })
                .error(function() {
                    return {};
                });
        }
    };

    return Authors;
}]).

factory('Articles', ['$http', 'Authors', function($http, Authors){
    var Articles = {

        data: {},

        query: function(){
            return $http.get('/api/articles.json')
                .success(function(result) {
                    Articles.data = result; // How to get the author info into this JSON object???
                })
                .error(function() {
                    Articles.data = [];
                });
        }
    };
    return Articles;
}])

これが完全に間違ったアプローチであるかどうかも教えてください。:)

4

3 に答える 3

6

APIと通信するときは、サービスを構造化するために次のアプローチをお勧めします(Misko Heveryのアドバイスに従って)。

    // Author model/service
    angular.module('myApp').factory('Author', function($http) {
      var Author = function(data) {
        angular.extend(this, data);
      };

      Author.get = function(id) {
        return $http.get('/authors/' + id).then(function(response) {
          return new Author(response.data);
        });
      };

      return Author;
    });

    // Article model/service
    angular.module('myApp').factory('Article', function($http) {
      var Article = function(data) {
        angular.extend(this, data);
      };

      Article.query = function() {
        return $http.get('/articles/').then(function(response) {
          var articles = [];
          angular.forEach(response.data, function(data){
            articles.push(new Article(data));
          });
          return articles;
        });
      };

      return Article;
    });

    // Your controller
    angular.module('myApp')
      .controller('Ctrl'
        ,[
          '$scope'
          ,'Article'
          ,'Author'
          ,function($scope, Article, Author){
            Article.query()
              .then(function(articles){
                $scope.articles = articles;
                attachAuthors(articles);
              });

            function attachAuthors(articles){
              angular.forEach(articles, function(article){
                Author.get(article.authorId)
                  .then(function(author){
                    article.author = author;
                  });
              });
            }

          }
        ]
      );

ただし、確かに、このすべてのデータを個別の呼び出しでフェッチすることはお勧めしません。代わりに、可能であれば、APIで結合されたJSONを返すようにする必要があります。サーバー側の結合は何倍も高速になります。

于 2013-02-21T20:33:44.603 に答える
2

JSOGをご覧ください。このようなことをするのに最適です。現在、Java、Python、Javascript、および Ruby 用のサーバー実装があります。クライアントの JavaScript 側では、JSOG.decode(object) を呼び出すだけです。私はAngularでそれを多用しています。

https://github.com/jsog/jsog

于 2014-02-22T17:12:32.113 に答える
0

1つのオプションは、サーバー上でこのすべてのデータを結合し、別のjsonファイルを作成することです。これにより、クライアント側が簡素化され、必要なHTTPリクエストは2つではなく1つになります。

両方のサービスを維持している場合(これは悪いアプローチではありません)、一方を起動し、応答を待ってから2番目を起動できます。たぶんArticles最初に、次にAuthors

Articles.get(function (articles) {                
            $scope.articles = articles;
            //fire query for Authors
            Authors.query(function (authors) {
              $scope.authors= authors;
              //combine both articles and authors
              combineData(articles, authors);                    
           }) 
});

データを組み合わせる関数は次のとおりです。

function combineData(articles, authors){
  $.each(articles, function (i, article) {
      //find author
      var author = $.grep(authors, function(a, j){
                     return a.id == article.authorId;
                   });
      //set article's author
      article.author_info = author;
    });
}

$scope.articlesこの構成では、を呼び出す前でも、記事が(設定によって)レンダリングされることに注意してください。Authors.query

于 2013-02-21T20:18:50.720 に答える