How to delay get request until async function finishes loading

Tags: , ,



In my express server, the root get request happens before an async function finishes listing the files from a database, but the get request needs information from the function to properly render the page. How can I have the get request wait until the other function is done?

I have looked at other solutions:

Request – Wait till API call is completed Node.js

How to get Express Node route to wait for function before rendering

Wait a async operation before execute render in express using NodeJs

But the answers don’t seem universal enough for my problem.

async function listFiles() {

  artWorks = [];

  const [files] = await storage.bucket(bucketName).getFiles();

  files.forEach(file => {
    function splitStr(str) {
      var string = str.split("/");
      artWorks.push(
        {
          imgCategory: string[0],
          subCat: string[1].replace(/-/g, ' '),
          imgSrc: bucket + file.name,
          thumbnail: thumbBucket + file.name.split('.')[0] + "-thumb.jpg",
          alt: string[2]
        });
    }
    var str = file.name;
    splitStr(str);
  });
  console.log("files listed");
}


listFiles().catch(console.error);


app.get("/", function(req, res) {
  let randomArt = Math.floor(Math.random()*artWorks.length);
    setTimeout(() => {
      res.render("index", {
          randomArt: randomArt,
          artWorks: artWorks
        })
    }, 500);
});

You can see my current solution is to put the res.render inside a setTimeout in order to get it to wait, but I have set an arbitrary amount of time and sometimes it doesn’t work. The page it renders "index" uses a randomly selected index of the artWorks array and if the array index is higher than 50 then the listFiles() function has not finished and it fails to load the home page saying:

TypeError: Cannot read property 'imgCategory' of undefined

Some notes:
The listFiles() function needs to remain independent of the get request as I call it in other parts of the code outside of the root get request.

The first time someone visits the site it will throw the error and not render the page, but upon refresh the artWorks array has finished and the page will render, I assume because it has cached the necessary information by that point.

So what is the best way to make the render wait while still keeping the function independent?

Answer

Wait for the promise to resolve after it’s called by changing:

listFiles().catch(console.error);

To:

listFiles()
  .then(() => {
    app.get("/", function(req, res) {
      let randomArt = Math.floor(Math.random()*artWorks.length);
      res.render("index", {
        randomArt: randomArt,
        artWorks: artWorks
      })
    });
  })
  .catch(console.error);


Source: stackoverflow