How to use promise with two http requests

删除回忆录丶 提交于 2019-12-31 05:27:11

问题


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

});

回答1:


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;

});



回答2:


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

});



回答3:


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;

     })
});


来源:https://stackoverflow.com/questions/31695152/how-to-use-promise-with-two-http-requests

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!