Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS combining web service responses

I have two web services:

One returns "Articles" like this:

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

And the other one returns an "Author" like this, given an id:

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

I want to combine the two, so I can display the authors name and photo in an article overview list.

Like this:

[   
    {
        "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"
        }
    }
]

I have an "Articles" service that fetches the articles, but what's the best approach for enriching the returned JSON with the author info from the similar "Authors" service before returning the "Articles" service output?

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;
}])

Please also tell me if this is an entirely wrong approach. :)

like image 857
Jakob Løkke Madsen Avatar asked Feb 21 '13 20:02

Jakob Løkke Madsen


People also ask

Which AngularJS service allows interacting with a RESTful backend?

AngularJS's $resource service is easier to use than $http for interacting with data sources exposed as RESTful resources.

What is$ http in AngularJS?

$http is an AngularJS service for reading data from remote servers.

What is asynchronous in AngularJS?

AngularJS allows to define async functions. An example is the $http service. HTTP service calls an API and returns a response as a promise. $http. get(url) .

What is API integration in Angular?

The AngularJS Global API is a set of global JavaScript functions for performing common tasks like: Comparing objects. Iterating objects. Converting data.


2 Answers

When communicating with API, I would recommend the following approach to structuring your services (as 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;
                  });
              });
            }

          }
        ]
      );

But for sure, I would also advise against fetching all this data in separate calls. Instead, if possible, you should have your API return you the combined JSON. Server-side combining would be many times faster.

like image 85
Stewie Avatar answered Nov 15 '22 04:11

Stewie


Check out JSOG. It is perfect for doing this sort of stuff. There are currently server implementations for Java, Python, Javascript and Ruby. On the client javascript side, you just call JSOG.decode(object). I use it heavily with Angular.

https://github.com/jsog/jsog

like image 30
Public Profile Avatar answered Nov 15 '22 05:11

Public Profile