Make synchronous MySQL queries in NodeJS - mysql

I have been doing google searches for 5 days, I hope to find the solution ... I know that it does not work because it is asynchronous, but I need the program (it is a Discord bot) to respond with a data that I get from a DB. I have tried Promises and callbacks, but I do not know if it is because I am a novice with asynchronous, that nothing works for me.
const con = mysql.createConnection({
host: datos.host,
user: datos.user,
password: datos.password,
database: datos.database
});
function leerPromesa() {
var promise = new Promise(function (resolve, reject) {
con.query('SELECT * from ranking;', function (err, rows, fields) {
if (err) {
reject(err);
return
}
resolve(rows);
rows.forEach(element => console.log(element));
})
});
return promise;
};
var promesa = leerPromesa();
promesa.then(
function (rows) {
rows.forEach(element => msg.reply(element));
},
function (err) {
msg.reply(err);
}
);
con.end();
What the bot does is respond with blank text.

First, you're not really connecting to database.
If you refer to docs https://github.com/mysqljs/mysql:
var connection = mysql.createConnection({
host : 'localhost',
user : 'me',
password : 'secret',
database : 'my_db'
});
// then connect method
connection.connect();
So your code will never work..
Second, you are closing connection before any query execution:
con.end();
Correct is to close connection after leerPromesa function execution.
Finally, code could look something like this:
const con = mysql.createConnection({
host: datos.host,
user: datos.user,
password: datos.password,
database: datos.database
});
con.connect();
function leerPromesa() {
return new Promise(function(resolve, reject) {
con.query("SELECT * from ranking;", function(err, rows, fields) {
if (err) {
return reject(err);
}
return resolve(rows);
});
});
}
leerPromesa()
.then(
function(rows) {
rows.forEach(element => msg.reply(element));
},
function(err) {
msg.reply(err);
}
)
.finally(function() {
con.end();
});
I used finally method on Promise to close connection in every situation https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Promise/finally

Related

AWS Lambda nodejs mysql query inside loop is not working

module.exports.handler = async (event, context, callback) => {
context.callbackWaitsForEmptyEventLoop = false;
let index = 0;
var client = mysql.createConnection({
host: process.env.rds_host,
user: process.env.rds_username,
password: process.env.rds_password,
port: process.env.rds_port
});
client.connect((err) => {
if (err) throw err;
console.log("Connected!");
});
let array = [];
let queries = ["query1", "query2", "query3", "query4"];
queries.map(q => {
array.push(getQueryResult(client, q));
});
Promise.all(array).then(result => {
console.log(result);
});
callback(null, {});
};
const getQueryResult = async (client, query) => {
return new Promise((resolve, reject) => {
client.query(query, function (err, result) {
if (err) {
reject(err);
}
resolve(result);
});
});
};
Above is my lambda scripts to execute multiple query from mysql. The problem is I didn't get any result and error message from above scripts. Please help me something is missing inside my scripts?
The issue is >> code is not waiting to finish Promise
You can resolve by :
Add callback in then
Promise.all(array).then(result => {
console.log(result);
callback(null, {});
});
OR
Use await
let result = await Promise.all(promiseArray);
console.log(result)
callback(null, {});
Note: Use try-catch to handle error in for await
Also, don't use map to loop array instead use For loop.
There are two or three (potential) issues with your code above:
Your if statement does not get evaluated because of the typeof client predicate does not return true.
your mysql port conflicts with your localhost port (assumption)
Change your if block as such:
// check if `dotenv` has been called if you use it
require('dotenv').config();
// access the state property on mysql object
// if you have closed your connection previously
// this will get evaluated by the parser
if (mysql.state === "disconnected") {
var client = mysql.createConnection({
host: process.env.rds_host,
user: process.env.rds_username,
password: process.env.rds_password,
port: process.env.rds_port // is your port the same as your localhost?
// include your database name here
});
// I suggest you to await your client connection
// since mysql executes sequentially, not asynchronously
client.connect(function(err) => {
if (err) {
console.error('error connecting: ' + err.stack);
return;
}
console.log("Connected!");
});
}
if the error persists, it means that your enviroment variables are not set correctly so your db configuration should be reviewed (see inline comments).

How to make a function to query MySQL in NodeJS?

I made this:
const mysql = require('mysql2/promise')
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: '',
database: 'nodejs',
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0
})
async function query(query) {
const result = await pool.query(query)
return result[0]
}
console.log(query('SELECT * FROM `users`'))
and I got back
Promise { <pending> }
How do I get back my results from querying the database, just like PHP can do?
In PHP I never had to do such a thing like async/await and promises...
I also tried using mysql:
const mysql = require('mysql')
const db = mysql.createConnection({
host : 'localhost',
user : 'root',
password : '',
database : 'nodejs'
})
function query(query) {
db.query(query, (err, result) => {
if (err) throw err
return result
})
}
console.log(query('SELECT * FROM `users`'))
but I got an undefined result
try this:
var mysql = require('mysql');
var con = mysql.createConnection({
host: "localhost",
user: "yourusername",
password: "yourpassword",
database: "mydb"
});
// function definition
function runQuery (con, sqlQuery) {
return new Promise((resolve, reject) => {
console.log("START");
if(con){
con.connect(function (err) {
if (err) throw err;
});
if (sqlQuery) {
con.query(sqlQuery, function (error, result, fields) {
connection.end(); // end connection
if (error) {
throw error;
} else {
return resolve(result);
}
});
} else {
connection.end(); // end connection
// code: handle the case
}
} else {
// code: handle the case
}
});
}
var sqlQuery = 'SELECT * FROM tableName';
// function call and pass the connection and sql query you want to execute
var p = runQuery(con, sqlQuery);
p.then((data)=>{ // promise and callback function
console.log('data :', data); // result
console.log("END");
});
I am not very familiar with MySQL and the libraries that you are using.
However, the Promise { <pending> } response that you are getting is because you didn't await your query execution.
Since the function is marked as async and is also performing an async action, it returns a Promise that needs to be awaited to be resolved.
The code below should work:
const mysql = require('mysql2/promise')
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: '',
database: 'nodejs',
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0
})
async function query(query) {
const result = await pool.query(query)
return result[0]
}
(async () => {
const queryResult = await query('SELECT * FROM `users`');
console.log(queryResult);
} )();
To understand how async-await works, consider the code below:
console.log('I will get printed first');
const asyncFunction = async () => {
await setTimeout(()=> {}, 1000)
console.log('I will get printed third');
return 'hello'
}
(async () => {
const result = await asyncFunction();
console.log(`I will get printed last with result: ${result}`);
})();
console.log('I will get printed second');
The console.log statement I will get printed last with result will wait for the asyncFunction to complete execution before getting executed.
Try this:
var mysql = require('mysql');
var con = mysql.createConnection({
host: "localhost",
user: "yourusername",
password: "yourpassword",
database: "mydb"
});
con.connect(function(err) {
if (err) throw err;
con.query("SELECT * FROM customers", function (err, result, fields) {
if (err) throw err;
console.log(result);
});
});

Node exports MySQL Pool Cluster

I'm new to node and I'm trying to use a MySQL pool cluster in but I'm not exactly sure how to export it.
At the moment I have the following in /libs/mysql.js:
poolCluster.add('db1', {
host: config.databases.hostname,
user: config.databases.db1.username,
password: config.databases.db1.password,
database: config.databases.db1.database,
connectionLimit: config.databases.connectionLimit
});
poolCluster.add('db2', {
host: config.databases.hostname,
user: config.databases.db2.username,
password: config.databases.db2.password,
database: config.databases.db2.database,
connectionLimit: config.databases.connectionLimit
});
module.exports = {
getConnection: (callback) => {
return poolCluster.getConnection(callback);
}
};
I'm trying to use it in models/monitor.js as below:
let poolCluster = require('../libs/mysql');
let moment = require('moment');
exports.select = function (sql, values, callback) {
poolCluster.getConnection('db1', (err, connection) => {
if (err) {
callback(err);
} else {
connection.query(sql, values, (err, result) => {
connection.release();
if (err) {
console.log(err);
callback(err);
} else {
callback(null, result)
}
})
}
})
};
The issue now is I'm getting an error stating cb is not a function.
Is this the correct way to export a mysql pool cluster in node?
You are exporting as getConnection: (callback) => {} but you are calling the same function with getConnection(string, callback).
According to the doc:
You can call getConnection like:
// Target Group : ALL(anonymous, MASTER, SLAVE1-2), Selector : round-robin(default)
poolCluster.getConnection(function (err, connection) {});
// Target Group : MASTER, Selector : round-robin
poolCluster.getConnection('MASTER', function (err, connection) {});
So, basically you need to pass the arguments you are getting from YOUR getConnection function to mysql's getConnection function. So this should do the trick:
module.exports = {
getConnection: (...args) => {
return poolCluster.getConnection(...args);
}
};

Node.js MySQL connection with timer and error handling

I have a basic node.js app running as a service on RaspPi.
There should be two important issues:
Check MySQL database every 3 secs and get Status
Never throw even if internet connection is lost or MySQL server stops etc.
This code runs well but app closes and throw an error if MySQL server stops. It needs to be run even if there is an any kind of error. (No need to log and get error type)
And also; is this every 3 secs connection algorithm correct for performance?
var mysql = require('mysql');
var con = mysql.createConnection({
host: "192.168.1.100",
user: "test",
password: "test",
database: "test"
});
var Gpio = require('onoff').Gpio;
var LED = new Gpio(4, 'out'); //use GPIO pin 4
var getStatus = setInterval(checkStatus, 3000);
function checkStatus() {
try
{
con.connect(function(err) {
//if (err) throw err;
con.query("SELECT device_status FROM Device_Status WHERE
device_id='device01'", function (err, result, fields) {
if (err)
{
//console.log(err);
}
else
{
//console.log(result[0].device_status);
if(result[0].device_status == "1")
{
LED.writeSync(1);
}
else
{
LED.writeSync(0);
}
}
});
});
}
catch(err){ //console.log(err);
}
}
Have you thought about pooling connections? Then you would connect on every query.
connect() {
return new Promise((resolve, reject) => {
pool = mysql.createPool({
connectionLimit: 10,
host : this.host,
user : this.user,
password : this.password,
database : this.database
});
resolve(pool);
});
}
Then you would search like this:
search(collection, searchStr) {
return new Promise((resolve, reject) => {
pool.getConnection((err, connection) => {
if (err) {
resolve(err);
} else {
var sql = "SELECT * FROM " + collection
if (searchStr)
sql += " WHERE " + searchStr;
connection.query(sql, (err, result) => {
if (err) reject(err);
resolve(result);
connection.release();
});
}
});
});
}
Can you check this code from my repo https://github.com/MathewJohn1414/node-mysql-quickstart
. It is uses the MySQL connection pool and the connection errors are also handled.

nodejs mysql using data in other modules/files

I'm trying to get data from my DB and use it in different modules of my app. My app is split in a lot of modules which I require where I need them.
My connectDB.js module looks like this
var mysql = require('mysql');
var db = mysql.createConnection({
host: "localhost",
user: "root",
password: "pw",
database : "something"
});
db.connect(function(err){
if(err){
console.log('Error connecting to Db');
return;
}
console.log('Database connected');
});
function select(query)
{
db.query(query,function(err,rows){
if(err) throw err;
return rows;
});
}
module.exports =
{
select
}
I was hoping to simply just require this module and then do a something like
db.select('SELECT * FROM users');
But for some reason the return value is always "undefined"
Sending queries inside the connectDB module works as expected returning the correct data. But I can't use my function to get data.
Is there something wrong here with my logic? Can you help what I am doing wrong?
As I remember, connection.query will return result async, so you need to wrap it with callback or Promise.
var mysql = require('mysql');
function DB {
var db = mysql.createConnection({
host: "localhost",
user: "root",
password: "pw",
database : "something"
});
db.connect(function(err){
if(err){
console.log('Error connecting to Db');
return;
}
console.log('Database connected');
});
this.select = function(query, callback) {
db.query(query,function(err,rows){
if(err) throw err;
callback(rows);
});
}
//Promise version
this.selectPromise = function(query) {
return new Promise(function(resolve, reject){
db.query(query,function(err,rows){
if(err) reject(err);
resolve(rows);
});
});
}
}
module.exports = DB;
How to use:
var DB = require('your-module');
var db = new DB();
db.query('select * from table', function(result) {
console.log(result);
});
db.selectPromise('select * from table').then(function(result) {
console.log(result);
});
Make the following change to your code
module.exports =
{
select: select
}
And you forgot about callback function
function select(query, callback)
{
db.query(query,function(err,rows){
if(err) throw err;
return callback(rows);
});
}
Then you can pass a function like this:
db.select('SELECT * FROM users', function(rows) {
// Do stuff with rows
});