0

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.

2 Answers 2

1

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);
    });
Sign up to request clarification or add additional context in comments.

2 Comments

@charlietfl Glad to help. Remember that .then() and .catch() both create new promises. They don't have an effect on promises further upstream.
yup.. created a plunker to see this for myself better
0

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.

3 Comments

This doesn't do the same thing. It doesn't allow for all requests to be completed before proceeding
@charlietfl : agree, this does not answer my question . I want all of the task to get the project owner to run asynchronously and then when ready , I get the full list of owner.
Sorry, did not see that constraint anywhere in the question. My answer answers the original question based on the wording.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.