Kode
Kode

Reputation: 3215

Nested Axios Call Only Returns First Value to Array

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

Answers (2)

SomoKRoceS
SomoKRoceS

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

Tibrogargan
Tibrogargan

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

Related Questions