Wait For Firebase Storage Database Pull To Finish Before Rendering Template In Nodejs With Async-await
I am trying to pull some images that are stored in firebase storage, create publicly accessible url's, then add them to an array which will be passed in as I render my template. However, each time my template renders first before the data is pulled and thus the array is empty. I basically need to find a way to render the template only when all the database pull is finished and I don't know how.I have dipped into async-await as a means to try to fix this problem but I have had no luck.
Here is my code:
async function readFiles () {
const [files] = await bucket.getFiles({ prefix: 'Resources/'});
files.forEach(file => {
//we have to get a signed public url in order to access the files stored in the cloud
file.getSignedUrl(signConfig, function(err, url) {
if (err) {
console.error(err);
return;
}
// The file is now available to read from this URL.
request(url, function(err, resp) {
resources.push(url) //append all the publicly avaialbe url's to the resources array
resp.statusCode = 200;
console.log("done request")
});
});
});
console.log("DONE READ FILES");
};
async function returnIndex() {
await readFiles(); //wait until read files is finished
console.log("TCL: returnIndex -> resources", resources);
res.render('advertiser/index.html', {resources: resources});
};
returnIndex();
And then here is my output(5 things stored in my database), basically indicating that all the public url's are added to the array after my template is rendered:
DONE READ FILES
TCL: returnIndex -> resources []
done request
done request
done request
done request
done request
Answer
Found a solution. It was to set a timeout for 0 ms... not sure exactly why this works but I think it has to do with the difference in a microtask vs a macrotask on the event loop... Promises are microtasks and Settimeout is a macrotask, so the Settimeout will be executed last and thus the information from the database is pulled correctly
var resources = new Array();
const [files] = await bucket.getFiles({ prefix: 'Resources/'});
// Lists all resources in their bucket
function readFiles () {
files.forEach(file => {
file.getSignedUrl(signConfig, function(err, url) {
if (err) {
console.error(err);
return;
}
resources.push(url)
// The file is now available to read from this URL.
request(url, function(err, resp) {
resp.statusCode = 200;
});
});
});
setTimeout(function(){res.render('advertiser/index.html', {resources: resources})}, 0);
};
readFiles();
Related Questions
- → Maximum call stack exceeded when instantiating class inside of a module
- → Browserify api: how to pass advanced option to script
- → Node.js Passing object from server.js to external modules?
- → gulp-rename makes copies, but does not replace
- → requiring RX.js in node.js
- → Remove an ObjectId from an array of objectId
- → Can not connect to Redis
- → React: How to publish page on server using React-starter-kit
- → Express - better pattern for passing data between middleware functions
- → Can't get plotly + node.js to stream data coming through POST requests
- → IsGenerator implementation
- → Async/Await not waiting
- → (Socket.io on nodejs) Updating div with mysql data stops without showing error