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?
Advertisement
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);