xtiger
xtiger

Reputation: 1446

$http request over a loop and assemble data in Angularjs

I have a piece of source code like this

var projectPromises = $http.get('http://myapi.com/api/v3/projects?private_token=abcde123456');

  $q.all([projectPromises]).then(function(data) {
    console.log(data);
    return data[0];
  }).then(function(projects) {
    var data = projects.data;
    var promises = [];
    var file = [];
    for(var i = 0; i < data.length; i++){
       var url = 'http://myapi.com/api/v3/projects/' + data[i].id + "/owner";
       promises.push($http.get(url));

    }

    console.log(promises);
    $q.all(promises).then(function(user) {
      console.log(user);
    }, function(error) {
      console.log("error here");
      console.log(error);
    });

Let me explain my source code.

First, I have the first API which will return a list of projects and I assign to projectPromises. After I get the list of projects , each project will contain a project ID . I will loop over the projects list and fire the corresponding http request to get the owner of a project.

After that , I use Angular q module to defer the list of promises and log the list into the console

console.log(user);

It does not log anything here . I try to print the error and I know the reason is that not all projects contain the users list. If not , it will return 404 , and 200 for vice versa. So the promises list will contain both 200 and 404 object return from the API , so I guest that when use q to defer the promises , it throw the error if the object is 404. But I don't know how to fix this.

My final purpose is to get the owner for each project and they will be populated into an array.

Upvotes: 0

Views: 1139

Answers (2)

JLRishe
JLRishe

Reputation: 101768

There's no need to use $q.all() unless you have multiple promises. $http.get() returns a promise, so you can just call .then on that promise.

Once you have the list of project IDs, you can map that to a set of promises that each have a .catch() to provide a fallback value if their respective request fails.

Once you have that, you can use $q.all() on the array of promises, then one more .then() and you should be all set.

var pProjects = $http.get('http://myapi.com/api/v3/projects?private_token=abcde123456');

pProjects
    .then(function (result) {
        // map the project IDs to an array of promises for each project's owner
        var pProjectOwners = result.data.map(function (proj) {
            return $http
               .get('http://myapi.com/api/v3/projects/' + proj.id + '/owner')
               .then(function (result) { return result.data; })
               // fallback value to use when a request fails
               .catch(function () { return 'no owner'; });
        });

        return $q.all(pProjectOwners);
    })
    .then(function (projectOwners) {
        console.log(projectOwners);
    })
    .catch(function (error) {
        console.error("something went wrong", error);
    });

And here's an alternate version with some refactoring to separate out the operation to get a project's owner:

function getProjectOwner(projectId) {
    return $http
       .get('http://myapi.com/api/v3/projects/' + projectId + '/owner')
       .then(function (result) { return result.data; })
}

var pProjects = $http.get('http://myapi.com/api/v3/projects?private_token=abcde123456');

pProjects
    .then(function (result) {
        // map the project IDs to an array of promises for each project's owner
        var pProjectOwners = result.data.map(function (proj) {
            return getProjectOwner(proj.id)
               // fallback value to use when a request fails
               .catch(function () { return 'no owner'; });
        });

        return $q.all(pProjectOwners);
    })
    .then(function (projectOwners) {
        console.log(projectOwners);
    })
    .catch(function (error) {
        console.error("something went wrong", error);
    });

Upvotes: 1

Kyle Alwyn
Kyle Alwyn

Reputation: 71

You're making your promises overly complicated. You can bind directly to your http call to interact with the promise $http returns.

$http.get("http://myapi.com/api/v3/projects?private_token=abcde123456").then(function (results) {
   // projects will be your array of projects
   var projects = results.data;

   // Use native Array for each to get reference to every object in array
   projects.forEach(function (project) {
     $http.get("http://myapi.com/api/v3/projects/' + project.id + "/owner").then(function (results) {
       var data = results.data;
       console.log(data); // This will log your owner
     });
   })
});

You should probably just nest your owner with the returned project json to limit these extraneous http requests, but that's a matter of server side architecture.

Upvotes: 0

Related Questions