2013-02-21 63 views
5

我有兩個Web服務:AngularJS合併Web服務響應

一個回報「文章」是這樣的:

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

而另外一個返回「作者」這樣,給定一個ID:

{ 
    "id": "1", 
    "name": "Test Name", 
    "email": "[email protected]", 
    "photo": "path/to/img" 
} 

我想將兩者結合起來,所以我可以在文章概覽列表中顯示作者姓名和照片。

像這樣:

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

我有一個「公司章程」的服務,在返回之前獲取的物品,但什麼是最好的方法與來自類似的「作者」的作者信息豐富返回的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; 
}]) 

另請告訴我,這是一個完全錯誤的方法。 :)

回答

0

一個選項是將所有這些數據結合在服務器上,也許創建一個單獨的json文件。這將簡化客戶端,只需要一個HTTP請求而不是兩個。

如果你保持這兩種服務(這不是一個壞的方法),你可以啓動一個,等待答案並開啓第二個。也許做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

+0

謝謝你的建議,但是這將意味着獲取的每一篇文章的所有作者,對不對?這是很多流量。 – 2013-02-27 08:46:43

+0

不,代碼假定您可以獲取所有文章,完成後您將獲取所有作者。然後結合結果。只涉及兩個請求 – Ulises 2013-02-27 16:24:53

+0

@JakobLøkkeMadsen你弄明白了嗎? – Ulises 2013-03-14 20:19:48

6

在與API進行通信時,我會推薦以下方法來構建您的se rvices(如advised by 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。服務器端組合的速度要快很多倍。

+1

感謝您的建議+ Misko答案的鏈接。非常豐富。 – 2013-02-27 08:45:32

2

查看JSOG。這是做這種事情的完美之選。目前有用於Java,Python,Javascript和Ruby的服務器實現。在客戶端JavaScript端,你只需調用JSOG.decode(object)。我大量使用Angular。

https://github.com/jsog/jsog

+0

嗨@ jon-stevens,你說你在AngularJS上大量使用jsog,你能說你是怎麼做到的嗎? – 2015-05-08 19:51:44

+1

@JayrMotta謝謝你的提問!這很簡單,你只需'decode = JSOG.decode(data)',其中'data'是你的ajax請求的主體響應。在angular的情況下,我在$ http的'.success()'承諾中或在攔截器中執行此操作。 – 2015-05-10 21:04:43

+0

我這樣做是爲了在全球範圍內的工作JSON文本是derialized前: '''的JavaScript $ httpProvider.defaults.transformResponse.splice(0,0,功能(數據,headersGetter){ 如果(數據&& headersGetter( )['content-type'] ==='application/json'){ return JSOG.parse(data); } else { return data; } }); ''' 你覺得呢? – 2015-05-13 13:58:46