Home > Blockchain >  Javascript multiple await in nodejs app - is there a better way to code this?
Javascript multiple await in nodejs app - is there a better way to code this?

Time:09-06

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, as Promise.all will resolve to an array of fulfilment values that come in the same order as the array of promises you pass as argument.

  • getBooks should not need an array parameter, as it has all it needs to create the array itself and then return it.

  • Instead of .forEach and push, use .map and return.

  • res.data.results.books is not a promise, so it is not needed to await that 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.

  • Related