Reputation: 3215
I am nesting an Axios call in another in order to get the list of IDs from my first call and then loop through and for each ID get the status from a 2nd API call. It will only return the first status when I log the array, versus showing the full array.
I believe the issue may be in the promise chain... or if this is not waiting for the promises to complete before outputting the final array.
var responsearray = []
axios.get('https://myapi.net/api/role/allroles?pageSize=1000').then(function (response) {
for(var i = 0; i < response.data.roles.length; i++)
{
var entry = response.data.roles[i];
var entryid = entry.id;
return axios.get('https://myapi.net/api/role/score/' + entryid).then(function (response2) {
// Nested call per role to push to array
responsearray.push(response2.status)
});
}
}).catch(function (error) {
// handle error
console.log(error);
}).then(function () {
// always executed
// Return Array
console.log(responsearray);
});
Upvotes: 2
Views: 707
Reputation: 3053
It looks like the outer promise is being resolved since you are returning a value (which is the first inner promise, the first Axios
call inside the loop).
Then, when the outer promise resolved, the outer then
function is being called with the responsearray
that happens to hold the result of the first response2
(however it might even be empty since the second Axios
call may haven't been resolved yet).
So the flow is something like that:
First axios call => first Then is called => i=0, second axios call is **RETURNED** => first axios call is resolved => last then is called => (second axios may be resolved by now and responsearray is filled with the result for i=0) => console.log(responsearray)
Anyway, I would suggest using Promise.all
that gives you a promise that contains a collection of promises and resolve it only if all of the promises are resolved. You can read more about it here.
I would use it something like that:
var responsearray = []
axios.get('https://myapi.net/api/role/allroles?pageSize=1000').then(function (response) {
for(var i = 0; i < response.data.roles.length; i++)
{
var entry = response.data.roles[i];
var entryid = entry.id;
//pushing the promise into responsearray
responsearray.push(axios.get('https://myapi.net/api/role/score/' + entryid).then(function (response2) {
console.log(i + " resolved");
}).catch(function (error) {
// handle error
console.log(error);
});
})
console.log("Done pushing all the promises");
return responsearray;
}).catch(function (error) {
// handle error
console.log(error);
}).then(function (responsearray) {
console.log("outer axios is resolved");
// responsearray should have all the promises by now
Promise.all(responsearray).then((results) => {
console.log(results);
}).catch(function (error) {
// handle error
console.log(error);
});
});
Upvotes: 1
Reputation: 4603
If you know you're going to have a collection of Promises, use the methods that the Promise class gives you to handle that.
For example, you could use something like Promise.all()
to handle an array:
var responsearray = []
axios.get('https://myapi.net/api/role/allroles?pageSize=1000').then(
function (response) {
for(var i = 0; i < response.data.roles.length; i++)
{
// get a single Promise and append it to our collection
responsearray.push(axios.get('https://myapi.net/api/role/score/' + response.data.roles[i])
}
}
)
Promise.all(responsearray)
.then( responses => responsearray = doSomethingWith(responses) )
.catch(function (error) {
// handle error
console.log(error);
})
.then(function () {
// always executed
// Return Array
console.log(responsearray);
});
This may not suit your use case completely, since Promise.all()
is all or nothing (see this). There are other options for this, like Promise.allSettled()
Upvotes: 1