This code essentially gets some data from an api, and puts it in two arrays which I then render on a page using a rendering engine. It works, but I am wondering if there is a different approach to this that is better (because the first await call will have to complete before the second one does - maybe with Promise.all - but then how do I pass the arrays in to render? Most of the code examples I've seen directly return from Promise.all [return await Promise.all(etc)])
app.get('/', async (req, res) => {
const fic = [];
const non = [];
await getBooks(fic, API.URL_HARDCOVER_FICTION);
await getBooks(non, API.URL_HARDCOVER_NONFICTION);
res.render('layout', {results: {fic: fic, non: non}});
});
const getBooks = async (array, url) => {
await axios.get(url "?api-key=" API.Key)
.then( async res => {
const list = await res.data.results.books;
list.forEach( book => {
array.push(new Book(
book.primary_isbn13,
book.title,
book.author));
})
})
.catch(error => {
console.error(error);
});
return array;
}
CodePudding user response:
Some comments:
Yes, you can use
Promise.all. There is no issue with the order, asPromise.allwill resolve to an array of fulfilment values that come in the same order as the array of promises you pass as argument.getBooksshould not need anarrayparameter, as it has all it needs to create the array itself and then return it.Instead of
.forEachandpush, use.mapandreturn.res.data.results.booksis not a promise, so it is not needed toawaitthat expression.
Adapted code:
app.get('/', async (req, res) => {
const urls = [API.URL_HARDCOVER_FICTION, API.URL_HARDCOVER_NONFICTION];
const [fic, non] = await Promise.all(urls.map(getBooks));
res.render('layout', {results: {fic, non}});
});
const getBooks = async (url) => {
const res = await axios.get(url "?api-key=" API.Key);
return res.data.results.books.map(book => new Book(
book.primary_isbn13,
book.title,
book.author
));
};
I left out the error handling. First make sure this works and then add a try..catch block.
