connection.query(...).then is not a function - mysql

I am new to the node js . I am using node with express in my backend and mysql as database . I have the confusion while handling the async calling . In my code while i use .
return connection.query(qry).then(
function(result) {
console.log('Query executed');
resolve(result.rows[0]);
},
function(err) {
console.log('Error occurred', err);
reject(err);
}
)
I got error connection.query(...).then is not a function
connection.query(qry, function (err, rows, fields) {
});
is executed correctly.
Simple query i am not getting any problem . while execute the complex query the above one is not wait for complete query execution

To use .then() with mysql first you need to “promisify” the database client.That can be done by creating a wrapper class for the MySQL client.
Check this article for better understanding

I have not found that, we can use promise with connection.query('') function. As per mysqljs documentation we can pass callback function for getting result.
var mysql = require('mysql');
var connection = mysql.createConnection(...);
connection.query('SELECT * FROM table_name', function (error, results, fields) {
if (error) throw error;
console.log(result);
});

You need to import mysql, and also actually create the connection.
Just do:
var mysql=require('mysql');
var connection=mysql.createConnection({
host:'127.0.0.1',
port: '3306',
user:'root',
password:'12345',
database:'db'
});
connection.connect(function(error){
if(!!error){
console.log(error);
}else{
console.log('Connected!:)');
}
});

Related

Connecting to MySql database from AWS Lambda function using Node.js, no connect callback

I am trying to connect an external (not AWS) MySql server from an AWS Lambda function written in Node.js using nodejs14.x environment, but the connect() callback is not called.
I am been struggling with this problem since days, there are a lot of references to similar issues but I really tried all possible permutations of solutions I found.
I am deploying with SAM and testing both on local machine and on real AWS.
Here is the sample code of the lambda helper
const mysql = require('mysql');
exports.helloFromLambdaHandler = async () => {
const message = 'Hello from Lambda!';
console.info(`${message}`);
var sql = "SELECT 1+? AS sum";
var values = [1];
console.log("Doing createConnection");
const connection = mysql.createConnection({
/* my connection data */
});
console.log("Doing connect");
connection.connect( (err) => {
console.log("Inside connection callback");
console.log('connected as id ' + connection.threadId);
if(!err) {
console.log("DB connected, thread id is " + connection.threadId);
console.log("Doing query");
connection.query(sql, values, (err, result, values) => {
console.log("Inside query callback");
if(!err) {
console.log("Query ok!");
console.log(result);
connection.end();
} else {
console.log("Error executing query: " + err.message);
}
});
} else {
console.log("Error connecting db: "+ err.message);
}
});
console.log ("Returning...");
return message;
}
The log is
Hello from Lambda!
Doing createConnection
Doing connect
Returning...
The expected behaviour is that after "Returning..." I should see the log "Inside connection callback" then "Inside query callback" and then "Query ok!".
Instead the callback of connect() appears not invoked.
I know that I can call query() directly skipping connect() but also doing so I encounter same issue.
Any clue?
Thank you!
SOLUTION
As suggested by the accepted answer, returning a promise is the solution to let Node complete all the queue. Unfortunately it's not possible to complete the Lambda and leave it running in background in a safe manner, for what I understand.
I am investigating alternative solutions such as:
mysql2 library which supports promises natively
serverless-mysql npm package which handles shared db connections
Below the running demo code
const mysql = require('mysql');
exports.helloFromLambdaHandler = async (event, context) => {
const message = 'Hello from Lambda!';
console.info(`${message}`);
var sql = "SELECT 1+? AS sum";
var values = [1];
console.log("Doing createConnection");
const connection = mysql.createConnection({
/* my connection data */
});
console.log("Doing query");
const promise = new Promise( (resolve, reject) => {
connection.query(sql, values, (err, result, values) => {
console.log("Inside query callback");
if(!err) {
console.log("Query ok!");
console.log(result);
connection.end();
resolve(message);
} else {
console.log("Error executing query: " + err.message);
reject(err);
}
});
});
console.log ("Returning...");
return promise;
}
You are using async handler, thus your function probably completes before your connect() has a chance to execute.
To try to overcome the issue, you can use Promise as shown in AWS docs.

Need help understanding async/promises with mysql query

var mysql = require('mysql');
var con = mysql.createConnection({
host: "host",
user: "login",
password: "password",
database: "db"
});
con.connect(function (err) {
if (err) throw err;
console.log("Connected!");
function addTalentPoint(id,amount){
var sql = "SELECT RegValue FROM `Registry` WHERE RegChaId="+id+" AND RegIdentifier='TalentPoints'"
var endingTalentPoint = 0;
con.query(sql, function (err, result) {
if (err) throw err;
console.log("Starting Talent Point: "+result[0].RegValue);
endingTalentPoint = result[0].RegValue + amount
var sql = "UPDATE `Registry` SET RegValue="+endingTalentPoint+" WHERE RegChaId="+id+" AND RegIdentifier='TalentPoints'"
con.query(sql, function (err, result) {
if (err) throw err;
console.log(endingTalentPoint)
});
});
}
function getTalentPoint(id){
var sql = "SELECT RegValue FROM `Registry` WHERE RegChaId="+id+" AND RegIdentifier='TalentPoints'"
con.query(sql, function (err, result) {
if (err) throw err;
console.log("get talent point: "+result[0].RegValue);
});
}
addTalentPoint(4,5)
getTalentPoint(4)
});
My example output:
Starting Talent Point: 125
get talent point: 125
130
I have read through numerous blogs and tried using async / await and setting up promises but I'm not getting where I need to be. I'm trying to get the code to wait for addTalentPoint to finish before getTalentPoint executes. Is it just the nature of the beast that it sends the query off, and then continues on with the code? I could put getTalentPoint inside the callback under the UPDATE, but how can I know the update finished?
addTalentPoint is still doing async stuff - all those con.query calls are async - so unless you do the work in the callbacks, things will just be executed immediately (like your getTalentPoint function) - one solution would be to add a callback function to the addTalentPoint function. See the below changes:
//First, add a callback parameter
function addTalentPoint(id,amount,callback){
...
//next, use this callback when the work is done
if (err) throw err;
console.log(endingTalentPoint)
if (callback) callback(); //if a callback exists, call it
Now, use your new param:
addTalentPoint(4,5, function() {
//All done doing the work in addTalentPoint, lets do more things now!
getTalentPoint(4)
})

Node.JS and MySQL - queries lock up and execute extremely slowly

I am getting strange behavior using Node.JS and MySQL with this driver - https://github.com/mysqljs/mysql
Essentially, I have a button on the frontend that triggers an app.get that makes a query in the database and I can happily use the results in my backend.
This works nicely, until I press the button 4-5 times in a second, where as the queries lock up and I have to wait for 2-3 minutes until they continue executing. I have a similar write function that behaves the same way.
Is it possible this is a problem, because I'm trying to execute the exact same query asynchronously? I.e. do I have to limit this from the front end or is it a backend problem?
Any ideas on how to debug what exactly is going on?
// database.js
var mysql = require('mysql');
var pool = mysql.createPool({
connectionLimit: 100,
host : 'localhost',
user : 'secret',
password : 'secret',
database : 'mydb'
});
exports.getConnection = function(callback) {
pool.getConnection(function(err, connection) {
callback(err, connection);
});
};
// dbrw.js
var con = require('../config/database');
function read(id, done) {
con.getConnection(function(err, connection){
if(!err){
connection.query("SELECT * FROM users WHERE id = ?",[id], function(err, rows) {
connection.release();
if (err)
done(err);
if (rows.length) {
console.log("rows " + JSON.stringify(rows));
done(rows[0].progress);
};
});
}
else {
console.log(err);
}
});
}
exports.read = read;
// routes.js
var dbrw = require('./dbrw.js');
app.get('/read', isLoggedIn, function(req, res) {
dbrw.read(req.user.id, function(result) {
console.log(result);
});
});
// Frontend - angular app.js
$scope.tryread = function() {
$http.get('/read');
}
Thanks in advance for any input.
I see a few issues:
function read(id, done) {
con.getConnection(function(id, connection){...}
}
Notice how you overwrite the id passed to read by giving that same name to an argument of the callback to getConnection.
Also, your Express route doesn't actually end the request by sending back a response, which will make your browser time out the connection. At some point, it will even refuse to send more requests because too many are still pending.
So make sure to end the request:
app.get('/read', isLoggedIn, function(req, res) {
dbrw.read(req.user.id, function(result) {
console.log(result);
res.end(); // or `res.send(result)`
});
});
And a tip: you should use the callback calling convertion for Node, where the first argument represents an error (if there is any) and the second argument represents the return value.

NodeJS: How to stop code execution till create operation to MySQL completes

I have a very basic scenario, I am making a create operation call to MySQL in my NodeJS application. Once I get result of create operation (success or failure) I have to execute some code.
But now due to asynchronous behavior of NodeJS my code which is dependent on result MySQL create operation is getting executed before MySQL create operation sends results back.
Here is my code
calculation.js
var mysql = require("mysql");
var methods = {};
// Creating connection
methods.executeQuery = function(selectQuery, values){
var result;
var con = mysql.createConnection({
host: "localhost",
user: "root",
password: "*********",
database: "******"
});
// getting connection
con.connect(function(err){
if(err){
console.log('Error connecting to Db');
return;
}
console.log('Connection established');
});
con.query(selectQuery, values, function(err,rows){
if(err) throw err;
console.log(rows);
result = rows;
console.log(result);
return result;
});
}
module.exports = methods;
client.js
var execute = require("./calculate.js");
var selectQuery = 'INSERT INTO users (username,password) VALUES (?,?)';
var values = ['sohamsoham12','sohamsoham12'];
var insertedRowInfo = execute.executeQuery(selectQuery, values);
if(insertedRowInfo){
console.log("true");
}else{
console.log("false");
}
I don't know if I correctly understand your question (what is the "create operation", for example?). But...
You can try this solution: execute the query inside the connect success callback:
// getting connection and executing query
con.connect(function(err){
if(err){
console.log('Error connecting to Db');
return;
}
console.log('Connection established');
con.query(selectQuery, values, function(err,rows){
if(err) throw err;
console.log(rows);
result = rows;
console.log(result);
return result; // this can't work... you should invoke a callback function, here...
});
});
UPDATE:
After OP comment, I now fully understand the question... (sorry :-().
You just miss a bit of async behavior... :-)
You should simply change methods.executeQuery from
function(selectQuery, values) {
...
}
to
function(selectQuery, values, callback) {
...
}
Then, instead using
return result;
You should simply use
callback(err, result); // if any error occurred
or
callback(null, result); // if no error occurred
Then, in client.js, when calling the executeQuery method, instead of
var insertedRowInfo = execute.executeQuery(selectQuery, values);
You should simply do
execute.executeQuery(selectQuery, values, function(err, insertedRowInfo) {
if (err) {
// handle error
} else {
// handle success, using insertedRowInfo...
}
});

nodejs + mysql: how can i reopen mysql after end()?

code as follows:
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
port :"3306",
database :"mydb",
user : 'root',
password : '007007',
});
var isCon = true;
connection.connect(
function (err) {
console.log(isCon);
if (err) {
isCon=false;
console.error("error connecting :"+err);
return;
};
}
);
if(isCon){
connection.query('select * from tb_items', function(err, result) {
if (err) throw err;
console.log('The solution is: ', result);
console.log('The typeof solution is ',typeof(result));
debugger;
});
connection.end();
}
connection.connect(
function (err) {
console.log(isCon);
if (err) {
isCon=false;
console.error("error connecting :"+err);
return;
};
}
);
if(isCon){
connection.query('select * from tb_items', function(err, result) {
if (err) throw err;
console.log('The solution is: ', result);
console.log('The typeof solution is ',typeof(result));
debugger;
});
connection.end();
}
i just open()-->connect()-->query()-->end(),then did it again,but second time , there is a error : Error:Could not enqueue Handshake after invoking quiting .
question : maybe i can't reopen it after end().but i just wanna kwon ,if i end(),how can i reopen it?
no, you can't, just create another one. All state in the connection class only relevant for current connection, so having "reopenWithSameConfig" method is possible, but you should really do this from outside.
Also, you don't need to close connection on each query - just continue to reuse it without calling .end()
If you want multiple connections and automatic disposal of dead connections you should use Pool class.
One more note: your isCon check is incorrect, connection.query is called before connect() callback so it's always true. It's safe to just check error in query callback itself. If connection was not successful error is propagated to a queued command