I'm writing an Express API call that makes use of multiple Axios API calls inside of itself, and I am running into trouble.
The idea is that the Express API call receives a query parameter named "tags" which can contain anywhere from one to infinity tags, each separated by a comma. For example, the URL could be:
localhost:5000/api/stuff?tags=tech,history,culture,etc
I've been able to break down the tags into an array with each element being an individual tag.
const theTags = req.query.tags;
const tagsArray = theTags.split(",");
And this gives me an array that would look like this:
["tech","history","culture","etc"]
Now here's where I'm getting stuck: I have to go through each tag in that array and make an Axios call using each one. My initial thinking was that this could be done using the forEach method. Since each Axios API call is supposed to return an array of data that matches the contents of the tag, I thought this would be a good way to gather all the results from each call:
// Create a blank array outside of the forEach loop.
const sumOfStuffArray = [];
// Start the forEach loop.
tagsArray.forEach( (element) => {
// Make the API call for the current element
const response = axios.get(`https://api.somewebsite.io/blahblah/stuff?tag=${element}`);
// Pull the array from the data of the response
const responseArray = response.data.stuff;
// Do another forEach loop through the responseArray and...
responseArray.forEach( (anotherElement) => {
// ...push each element of the response array into the outside sumOfStuffArray
sumOfStuffArray.push(anotherElement);
}
}
This has not worked as each time I try and check the length of the sumOfStuffArray after the forEach method is supposed to have finished, it comes back with an empty array.
I'm positive this is because I'm missing something with async/await or .then statements, but I just can't figure out how to make it work!
Does anyone have any ideas what I need to do to compile all these array elements into a single array?
There're 2 things here:
axios.get is asynchronous, it returns a Promise, so you have to wait for its response before accessing with response.data.stuffforEach does not support asynchronous, it just executes callback for each element and does not wait for those callbacks to finish, so your result array is empty since the axios.get haven't responded yet.You can try wrap your forEach in a Promise to wait for it done to check the result array, and use async/await for axios.get to wait for it response:
// Create a blank array outside of the forEach loop.
const sumOfStuffArray = [];
const waitForEach = new Promise(resolve => {
tagsArray.forEach(async (element, index, array) => {
const response = await axios.get(`https://api.somewebsite.io/blahblah/stuff?tag=${element}`);
const responseArray = response.data.stuff;
responseArray.forEach( (anotherElement) => {
sumOfStuffArray.push(anotherElement);
}
// check the forEach finish
if (index === array.length - 1) {
resolve();
}
});
}).then(() => {
console.log(sumOfStuffArray);
});
Or better, use Promise.all for the tagsArray:
const tagsResponses = tagsArray.map(element => axios.get(`https://api.somewebsite.io/blahblah/stuff?tag=${element}`));
Promise.all(tagsResponses).then(responseArray => {
responseArray.forEach(response => {
sumOfStuffArray.push(response.data.stuff);
}
}).then(() => {
console.log(sumOfStuffArray);
});