Reputation: 1446
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
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
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