Returning undefined from mySQL - mysql

I know the database is connecting with the code as, when i console.log(res) with the code below it is returning the correct data,
const orm={
selectAll(){
connection.query('SELECT * FROM burgers', (err,res) => {
if (err) throw err;
console.log(res)
return res;
});
},
Yet when i console.log(burgers) from this function in the code below it is returning an undefined
app.get(`/`, function (req, res) {
const burgers = orm.selectAll();
console.log(burgers)
res.render(`index`, burgers);
});
I understand this may be a very simple answer but i personally just cannot work it out any help is welcomed.

selectAll is using a callback style method inside it. You can not get the response syncronously. You need to either pass the callback to selectAll or change it to use promise like this
function selectAll() {
return new Promise((reoslve, reject) => {
connection.query("SELECT * FROM burgers", (err, res) => {
if (err) {
reject(err);
}
reoslve(res);
});
});
}
You can then use it like this
app.get(`/`, function async (req, res) {
const burgers = await selectAll();
console.log(burgers)
res.render(`index`, burgers);
});

Your selectAll method will not return any value.
query get an lambda callback function as second parameter AND query is asyncron
One way is to return an Promise from selectAll
const orm = {
selectAll(callback) {
return new Promise((resolve, reject) => {
connection.query('SELECT * FROM burgers', (err, res) => {
if (err) {
reject(err);
} else {
resolve(res)
}
})
})
},
Than you can get your result:
app.get(`/`, function (req, res) {
orm.selectAll().then( burgers => {
console.log(burgers)
res.render(`index`, burgers);
});
});

Related

Mongoose updating and fetching in the same request

I have the following mongoose "update" path:
app.put('/update', async (req, res) => {
const newTaskName = req.body.todoName
const newDays = req.body.days
const id = req.body.id
try {
await TodoModel.findById(id, async (err, updatedTodo) => {
updatedTodo.todoName = newTaskName
updatedTodo.daysToDo = newDays
await updatedTodo.save()
res.send("updated")
})
} catch(err) {
console.log(err)
}
})
Separately I have a path that returns all data from the Mongo table:
app.get('/read', async (req, res) => {
TodoModel.find({}, (err, result) => {
if (err) {
res.send(err)
}
res.send(result)
})
})
How can I both update and send back the full updated list within the response?
Separate question, not necessary to answer, but would be nice - perhaps this approach is all wrong? some background:
In my MERN app I am calling to add an item to a list and then want to immediately render the updated list as currently read from the database, since I don't want to assume the insertion was successful
I tried using some asynchronous workarounds with no luck
Fixed!
Upon further inspection of Mongoose documentation, I found that by using the findOneAndUpdate method instead of findById, I am able to utilize a callback that will return the updated item:
app.put('/update', async (req, res) => {
const id = req.body.id
let updateSet = req.body
delete updateSet.id
try {
ShoppingModel.findOneAndUpdate({ _id: id }, { $set: updateSet }, { new: true }, (err, doc) => {
if (err) return console.log(err)
res.send(doc)
})
} catch (err) {
console.log(err)
}
})

Nodejs Mysql asynchronous

I'm trying to return my users list from my Mysql database through this endpoint.
The problem is that it return "undefined".
Do you know how to solv this?
Thx in advance :)
app.get("/users", async (req, res) => {
users = await query_my_users_from_db()
// Got "users = undefined" here
console.log(users)
return JSON.stringify(users)
})
async function query_my_users_from_db() {
var users = await db.query("SELECT * FROM `users`", function (err, result) {
if (err) throw err
users = Object.values(JSON.parse(JSON.stringify(result)))
return users
})
}
Since db.query is callback based, you should change your code into:
function query_my_users_from_db(callback) {
db.query("SELECT * FROM `users`", callback)
}
remove all the async\await since you are not using any promises!
then define your callback
const usersHandler = (err, result) => {
... do what you want with your users ...
}
and use it like this:
query_my_users_from_db(usersHandler)
Another option is to use some promise-based wrapper package for MySQL, there is plenty or use node util.promisify() (https://www.geeksforgeeks.org/node-js-util-promisify-method/) and then use async\await and remove the callback altogether.
Hope that it helps
I used this and it's working like a charm.
db.promise = (sql, params) => {
return new Promise((resolve, reject) => {
db.query(sql, params, (err, result) => {
if (err) {
reject(new Error())
} else {
resolve(result)
}
})
})
}
async function connection(query) {
const result = await db.promise(query)
return result
}
app.get("/users", async (req, res) => {
users = await connection("SELECT * FROM `users`")
return users
})

Return mysql query result using Promise

I'm currently a little confused as to how to properly wait for the promise to finish before returning the result from a query
Here is my current code:
const getLeaderboardValues = async () => {
const SQLConnection = await getSQLConnection();
return new Promise((resolve, reject) => {
SQLConnection.query(getValuesSQLQuery, (err, result) => {
if (err) { reject(err) }
return resolve(result);
});
SQLConnection.end()
})
}
const runtime = () => {
getLeaderboardValues().then((result) => {
console.log(result);
})
}
The code above does log the correct results while debbugging, i believe this is because i'm giving the code more time to render with the breakpoints, however when running normally i get undefined
I believe the SQLConnection.end() line is executing before the query is returned, given it is outside the query statement.
The below may solve your issue, however I do not recommend opening a connection and closing it on every request in production systems.
const getLeaderboardValues = async () => {
const SQLConnection = await getSQLConnection();
return new Promise((resolve, reject) => {
SQLConnection.query(getValuesSQLQuery, (err, result) => {
if (err) {
reject(err)
return SQLConnection.end()
}
SQLConnection.end()
return resolve(result);
});
})
}
const runtime = () => {
getLeaderboardValues().then((result) => {
console.log(result);
})
}

MySQL NodeJS .then() s not a function

Can't I use promise for nodeJS mysql query?
// My DB settings
const db = require('../util/database');
db.query(sqlQuery, [param1, param2])
.then(result => {
console.log(result);
})
.catch(err => {
throw err;
});
It is returning: TypeError: db.query(...).then is not a function
You mentioned in the comments that you want logic after the query block to be awaited, without placing that logic inside of the callback. By wrapping the method with a Promise, you can do that as such:
try {
const result = await new Promise((resolve, reject) => {
db.query(sqlQuery, (error, results, fields) => {
if (error) return reject(error);
return resolve(results);
});
});
//do stuff with result
} catch (err) {
//query threw an error
}
Something like this should work
function runQuery(sqlQuery){
return new Promise(function (resolve, reject) {
db.query(sqlQuery, function(error, results, fields) {
if (error) reject(error);
else resolve(results);
});
});
}
// test
runQuery(sqlQuery)
.then(function(results) {
console.log(results)
})
.catch(function(error) {
throw error;
});
mysql package does not support promise. We can use then only a function call returns a promise.You can use mysql2 which has inbuilt support for Promise. It will also make your code more readable. From mysql2 docs:
async function main() {
// get the client
const mysql = require('mysql2/promise');
// create the connection
const connection = await mysql.createConnection({host:'localhost',
user: 'root', database: 'test'});
// query database
const [rows, fields] = await connection.execute(query);
// rows hold the result
}
I would aslo recommend you to learn about callbacks, promise and async-await

Nodejs async/await for MySQL queries

I trying to execute 2 MySQL queries sequentially in Node.JS. MySQL queries work properly by itself.
I would like to do it with async/await function to be sure record is inserted before it's updated.
Here is the code:
router.post('/assign_new_item_id', async (req, res) => {
.....
try {
let qr1= "INSERT INTO foo1 ........;"
await pool.query( qr1, (err) => {
if (err) throw err;
});
let qr2= "UPDATE foo1 .....;"
await pool.query( qr2, (err) => {
if (err) throw err;
});
}catch(err){
console.log(err)
}
It seems that execution "hangs" within first await await block. What is the best way the ensure that both queries are executed consequently.
Thanks in advance for any help.
To await you need a Promise, Not Callback. In your case you are not returning a promise to await.
router.post('/assign_new_item_id', async (req, res) => {
// .....
try {
let qr1 = "INSERT INTO foo1 ........;"
await new Promise((res, rej) => {
pool.query(qr1, (err, row) => {
if (err) return rej(err);
res(row);
});
});
let qr2 = "UPDATE foo1 .....;"
await new Promise((res, rej) => {
pool.query(qr2, (err, row) => {
if (err) return rej(err);
res(row);
});
});
} catch (err) {
console.log(err)
}
});
Here I am promisifing the pool.query method and returning a promise.