I am new to Node-JS and trying to get to grips with the asynchronous concept and promises.
I am trying to ensure the availability of the DB-data at the moment the webserver is being rendered.
With the code I seem to have achieved the correct timing – the function buildhtml being called, when the data is available. A first success after a night of research.
Now I am trying to find the correct way of passing the data to the webserver / express.
The data I am looking for is now encapsulated in a promise-object and can’t be processed. I have looked at many other posts, but was not able to derive a solution for y example.
Question: What is the best practice solution to hand over the data in a consumptional way (basically the promise object, but without the outer promise encapsulation)? Is my thinking entirely wrong or is it just a little step I am missing?
Any answers are much appreciated and my thanks in advance!
//DB Load Users
const promise = new Promise((resolve, reject) => {
db.connect(function(err) {
if (err) throw err;
console.log("Connected!");
var sql = "SELECT username, useremail, userage, useruniqueid FROM users";
db.query(sql, function(err, result) {
if (err) throw err;
const jsonresult = JSON.parse(JSON.stringify(result)); //to clear RowDatePacket
resolve(jsonresult);
});
})
})
promise
.then(buildhtml)
//Render (express) HTML with promise resolve after DB-query
function buildhtml() {
app.get("/", function(req, res) {
res.render("home", {
data: promise
})
})
}
This was the output with console.log(promise) in buildhtml():
Connected!
Promise {
[
{
username: 'admin',
useremail: '888883895',
userage: '33',
useruniqueid: 1
},
{
username: 'admin',
useremail: '888883895',
userage: '22',
useruniqueid: 2
},
{
username: 'admin',
useremail: '888883895',
userage: '22',
useruniqueid: 3
},
{
username: 'admin',
useremail: '888883895',
userage: '22',
useruniqueid: 4
},
{
username: 'pushy boi',
useremail: '[email protected]',
userage: '65',
useruniqueid: 5
},
{
username: 'push attempt',
useremail: '[email protected]',
userage: '65',
useruniqueid: 6
},
{
username: 'instead of push db',
useremail: '[email protected]',
userage: '37',
useruniqueid: 104
},
{
username: '111',
useremail: '111',
userage: '11',
useruniqueid: 111
},
{
username: null,
useremail: null,
userage: null,
useruniqueid: 112
},
{
username: 'Max Mustermann',
useremail: '[email protected]',
userage: '44',
useruniqueid: 333
}
]
}
2
Answers
What you’ve got should work but introduces a potential race condition… what if a request is made to
GET /
before the promise resolves? Express will simply return a 404 because it does not know about the route.Instead of registering your route handler after the promise resolves, resolve the promise inside the route handler
Note that your query will only ever execute once when your Express server starts up. This may or may not be what you want. The more typical approach is to perform the query each time a request is made.
This is roughly how you should rewrite this. First, wrap the code that fetches the MySQL data in a function.
Note I changed your
throw
s intoreject
and removed the unneeded JSON step.Even better would be if you use a promise-based mysql library like
mysql2/promises
and use a connection pool:So clean in comparison!
Then you define your route and call
getUsers
when you need it: