Stranger B.
Stranger B.

Reputation: 9364

How to use promise with two http requests

I'm trying to make couple of HTTP requests, one inside another, and I'm having a trouble restructuring my JSON object.

I have a factory function, first of all i'm trying to get all the teams, each team has an Id, and then i'm getting all the news for each team with the id related, and putting that news in the first JSON object.

but this is not working !

.factory('teamsFactory', function ($http,CacheFactory,LocaleManager,$q) 
{

   teams.Getteams= function() 
    {
        var zis=this;
    var promise=$http({method:"GET",url:"http://www.myserver/teams"});
    promise.then(function(response){

    for (var i=0;i<response.data.length;i++) {

     zis.getTeamsNews(response.data[i].idTeam).then(function(newsresponse){

     response.data[i].news=newsresponse.data;

     });
    }


    },alert('error'));
    return promise;         
    }


    teams.getTeamsNews= function(idTeam) 
    {
    var promise=$http({method:"GET",url:"http://www.myserver.com/news?team="+idTeam});
    promise.then(null,alert('error'));
    return promise;         
    }

});

Upvotes: 0

Views: 2294

Answers (3)

Matt Herbstritt
Matt Herbstritt

Reputation: 4862

I think it's better to push all the $http promises into an array and then use $q.all() to group them together rather than calling them each individually in a loop. Try this:

Note I had to move some of your functions around and create dummy data etc. so you will have to alter it slightly to fit your app.

DEMO

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope, teamsFactory) {
  $scope.name = 'World';

  teamsFactory.Getteams()
  .then(function(data){
    $scope.teamsData = data;
  });

});

app.factory('teamsFactory', function ($http, $q){

  var teams = {};

  teams.getFavoriteTeamsNews = function(teamId){
    return $http
      .get('news.json')
      .then(function(response){
        console.log('gtTeamNews response', response);
        return response.data[teamId];
      })
  }

  teams.Getteams = function(){

    var zis = this,

        httpConfig = {
          method  : "GET", 
          url     : "teams.json"
        };

    return $http(httpConfig)
      .then(function(response){

        var teamId, promise,

            requests = [];

        for(var i = 0; i <response.data.length; i++){

          teamId  = response.data[i].idTeam;
          promise = teams.getFavoriteTeamsNews(teamId);

          requests.push(promise);

        }

        return $q
          .all(requests)
          .then(function(responses){

            angular.forEach(responses, function(newsresponse, index){
              response.data[index].news = newsresponse;
            });

            return response.data;

          });


      })
      .catch(function(error){
        console.log('error', error);
      });   

  }


  return teams;


  // teams.TeamsNews= function(idTeam){
  //   return $http({method:"GET",url:"http://www.myserver.com/news?team="+idTeam})
  //           .catch(function(){
  //             alert('error')
  //           });

  // }

});

update

You could also re-factor the above to take advantage of promise chaining which makes it much cleaner in my opinion. This should give the same output but is more 'flat', i.e. has less indentation/callback hell:

DEMO2

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope, teamsFactory) {
  $scope.name = 'World';

  teamsFactory.Getteams()
  .then(function(data){
    $scope.teamsData = data;
  });

});

app.factory('teamsFactory', function ($http, $q){

  var responseData,

      teams = {};

  teams.getFavoriteTeamsNews = function(teamId){
    return $http
      .get('news.json')
      .then(function(response){
        console.log('gtTeamNews response', response);
        return response.data[teamId];
      })
  }

  teams.Getteams = function(){

    var zis = this,

        httpConfig = {
          method  : "GET", 
          url     : "teams.json"
        };

    return $http(httpConfig)
      .then(function(response){

        var teamId, promise,

            requests = [];

        responseData = response.data;

        for(var i = 0; i < responseData.length; i++){

          teamId  = responseData[i].idTeam;
          promise = teams.getFavoriteTeamsNews(teamId);

          requests.push(promise);

        }

        return $q.all(requests);

      })
      .then(function(responses){

        angular.forEach(responses, function(newsresponse, index){
              responseData[index].news = newsresponse;
        });

        return responseData;
      })
      .catch(function(error){
        console.log('error', error);
      });   

  }


  return teams;

});

Upvotes: 1

gandra404
gandra404

Reputation: 6071

eventually something like that .. this is raw solution .. could be enhanced with caching ...

var module = angular.module('myapp', []);

module.factory('teamsFactory', function ($http,CacheFactory,LocaleManager,$q)
{

    function ExtractTeamFromData(data){
        // TODO
        console.log("TODO: Exctract teams from data ...");
    }
    function FindTeamById(teams, tgeamId){
        // TODO
        console.log("TODO: Find team by id ...");
    }
    function ExtractNewsFromData(data){
        // TODO
        console.log("TODO: Exctract news from data ...");
    }


    var GetTeams= function()
    {
        var zis=this;
        var promise = $http({method:"GET",url:"http://www.myserver/teams"});
        var successCallback = function(data, status, headers, config) {
            var teams = ExtractTeamFromData(data);
            return teams;
        };

        var errorCallback = function(reason, status, headers, config) {
            console.error("Some error occured: " + reason);
            return {
                'errorMessage': reason
            };
        }
        promise.then(successCallback,errorCallback);
        return promise;
    }



    var GetTeam = function(idTeam)
    {
        var promise = GetTeams();
        var successTeamsCallback = function(teams, status, headers, config) {
            return FindTeamById(teams, tgeamId);
        };
        var errorTeamsCallback = function(reason, status, headers, config) {
            console.error("Some error occured: " + reason);
            return {
                'errorMessage': reason
            };
        }
        promise.then(successTeamsCallback,errorTeamsCallback);
        return promise;
    }


    var GetTeamsNews = function(idTeam){
        var promise = GetTeam(idTeam);
        var successTeamCallback = function(team, status, headers, config) {
            var newsPromise = $http({method:"GET",url:"http://www.myserver.com/news?team="+idTeam});
            var successNewsCallback = function(data, status, headers, config) {
                var news = ExtractNewsFromData(data);
                return news;
            };
            var errorNewsCallback = function(reason, status, headers, config) {
                console.error("Some error occured: " + reason);
                return {
                    'errorMessage': reason
                };
            }
            newsPromise.then(successNewsCallback,errorNewsCallback);
            return newsPromise;
        };
        var errorTeamCallback = function(reason, status, headers, config) {
            console.error("Some error occured: " + reason);
            return {
                'errorMessage': reason
            };
        }
        promise.then(successTeamCallback,errorTeamCallback);
        return promise;
    }

    return {
        GetTeams: GetTeams,
        GetTeam: GetTeam,
        GetTeamsNews: GetTeamsNews
    };

});

Upvotes: 1

NeoPix
NeoPix

Reputation: 443

You need to create a promise of your own, and resolve it when done, this way :

return $q(function(resolve, reject) {

    $http({method:"GET",url:"http://www.myserver/teams"}).then(function(response){
        var promises = [];
        for (var i=0;i<response.data.length;i++) {
            promises.push(zis.getFavoriteTeamsNews(response.data[i].idTeam)).then(function(newsresponse){
                response.data[i].news=newsresponse.data;
            });
        }
        $q.all(promises).then(function(){
            resolve(response);
        });
    });

    for (var i=0;i<response.data.length;i++) {

     zis.getFavoriteTeamsNews(response.data[i].idTeam).then(function(newsresponse){

     response.data[i].news=newsresponse.data;

     })
});

Upvotes: 0

Related Questions