I'm trying to build a list of URLs by querying a database for book titles and authors, and then using that information to fetch data from an API. However, I'm facing an issue where the URL list is logged as undefined. Here's the code I'm working with: in an Express route, I'm querying a list of books, looping through each of them, and trying to make asynchronous calls with axios to get their cover URLs. The problem seems to be related to the scoping within my try-catch block. I need help figuring out how to properly push the data into a list that I can access later, say to render in my index.ejs template. Any insights?
2 Answers
You need to move your declaration of the `arr` variable outside of your forEach loop. Right now, you're creating a new array every time the loop runs, so it’s always empty when you try to render. Declare it before the loop, and then push values into that single instance of the array. Just make sure to get all axios calls settled first before rendering your page!
It looks like you’re trying to log `urlList` before the axios promises resolve. You should wait for all the axios calls to finish. A good way to do this is by using `Promise.all` along with `map` instead of `forEach`. This way, you can handle all promises at once. Just make sure to declare `urlList` outside the asynchronous flow so you can use it later.
Exactly! You can await the axios calls like this:
```javascript
const results = await Promise.all(result.rows.map(async (row) => {
try {
const response = await axios.get(`https://bookcover.longitood.com/bookcover?book_title=${row.title}&author_name=${row.author}`);
return response.data.url;
} catch (error) {
console.log(error.message);
return null;
}
}));
urlList = results.filter(url => url !== null);
console.log(urlList);
res.render('index.ejs', { urls: urlList });
```
That’s right! Something like this should work:
```javascript
let arr = [];
result.rows.forEach((row) => {
axios.get(`https://bookcover.longitood.com/bookcover?book_title=${row.title}&author_name=${row.author}`)
.then((res) => {
arr.push(res.data.url);
})
.catch((err) => console.log(err.message));
});
// Make sure to render after all axios calls are completed!