nodejs mysql variable access after promise - mysql

I'm beginner into nodeJS world and i try to connect a mysql database. I first select a team (equipe) and after that i have to select all the members of this team.
Finally, i want to construct an array with my teams and the members (in the lesEquipes var). When the code comes to the 3rd then, my var is null ! WHY please ?
Here is my code :
class Database {
constructor() {
this.connection = mysql.createConnection({
host: "192.x.x.x",
user: "john",
password: "mypass",
database: "mybase"
});
}
query(sql, args) {
return new Promise((resolve, reject) => {
this.connection.query(sql, args, (err, result, fields) => {
if (err) return reject(err);
resolve (result);
});
});
}
close() {
return new Promise((resolve, reject) => {
this.connection.end(err => {
if (err) return reject (err);
resolve();
});
});
}
}
var database = new Database();
.............
app.post('/visu',function(req,res){
//console.log(nodedump(req.params.mdp));
//console.log(req.body);
// codage en dur de l'authentification
if((req.body.email == "john#gmail.com") && (req.body.mdp == "password")){
var leUser = "administrateur";
let lesEquipes = new Array();
let test = 'Toto';
database.query("select * from equipe order by id")
.then( result => {
for (var i = 0; i < result.length; i++) {
let courante = new Array();
let nomEquipe = result[i].nomEquipe;
let idEquipe = result[i].id;
courante[0] = result[i];
var sql2 = "select * from participant where equipe = " + result[i].id;
//console.log(sql2);
database.query(sql2)
.then(result2 => {
console.log("Membres de l'équipe : " + nomEquipe);
courante[1] = result2;
console.log("COURANTE 2 "+ JSON.stringify(courante));
lesEquipes[idEquipe] = courante;
let test = 'AUTRE CHOSE';
/*
console.log("QUERY 2 "+ JSON.stringify(result2));
for (var j = 0; j < result2.length; j++) {
participant = result2[j].nom;
console.log(participant);
}
*/
//res.render('visuEquipes.ejs', { user:leUser, equipes:lesEquipes});
//console.log("Contenu "+ JSON.stringify(lesEquipes));
return ""; //database.query(sql3);
});
}
console.log("Contenu "+ JSON.stringify(test));
console.log("Contenu "+ JSON.stringify(lesEquipes));
}).then(result3 =>{
console.log("result 3 : "+result3);
console.log("Contenu "+ JSON.stringify(test));
**// THIS VAR IS NULL NULL NULL lesEquipes
console.log("Contenu "+ JSON.stringify(lesEquipes));**
res.render('visuEquipes.ejs', { user:leUser, equipes : lesEquipes});
}).catch((err) => {
console.log(err);
database.close();
});

The problem is that you are executing asynchronous code inside a loop.
for (var i = 0; i < result.length; i++) {
/**/
database.query(sql2).then(result2 => {
/**/
});
}
So in .then(result3 =>{ the variable lesEquipes is very likely to have not been initialized.
You have to wait for all the promises to resolve. You can easly add an array of promises.
const promises = [];
for (var i = 0; i < result.length; i++) {
promises.push(database.query(sql2).then(result2 => {/*...*/}));
}
return Promise.all(promises);
Or you can use async-p library to iterate the array, or better you can use ES7 async-await constructs.

Related

nodejs sequelize mysql async transaction FailedSequelizeDatabaseError The user specified as a definer ldgybxav_ph1_admin#49.37.47.142 does not exist

When ever I am trying to use asynchronous transaction in by node js app it is giving me an error during post request that user does not exist. But the same user credentials is working fine if I do a simple get or post from the same server and db.
router.post('/medicineretailsalereturn', async (req, res) => {
console.log("Medicine Retail Return Calls......");
console.log(req.body);
var sequelize = common.setPharmaDBConn4SQL(req.headers['pharma_id']);
const t = await sequelize.transaction();
try {
req.body.bill.med_sale_date = new Date();
req.body.bill.med_bill_number = billgenerator(3);
req.body.bill.record_created_date = new Date();
var medicineSellBill = await MedicineRetailSaleBill.create(req.body.bill, { transaction: t });
for (var medCount = 0; medCount < req.body.items.length; medCount++) {
var sellReturnJSON = req.body.items[medCount];
sellReturnJSON.med_bill_id = medicineSellBill.med_sale_bill_id;
sellReturnJSON.record_created_date = new Date();
if(sellReturnJSON.med_bill_number != null) sellReturnJSON.med_sell_bill_number = sellReturnJSON.med_bill_number;
if(sellReturnJSON.med_bill_number == null) {
sellReturnJSON.med_bill_number = medicineSellBill.med_bill_number;
console.log("Sell Deatils");
console.log(sellReturnJSON);
await MedicineRetailSaleDetails.create(sellReturnJSON, { transaction: t });
} else {
sellReturnJSON.med_bill_number = medicineSellBill.med_bill_number;
console.log("Sell Retun Deatils");
console.log(sellReturnJSON);
await MedicineRetailReturnDetails.create(sellReturnJSON, { transaction: t });
}
}
await t.commit();
res.status(200).send("Medicine Reatils Sell/Return Bill Number :" + medicineSellBill.med_bill_number);
} catch (error) {
console.log("Error :" + error)
await t.rollback();
res.status(200).send("Medicine Reatils Sell/Return Failed" + error);
}
});
I can share the entire code if needed. Any help will be highly appriciated.

Node JS callbacks in a while loop

I have a MySQL database with the table id which stores all the unique id's generated till date, using nanoid module. I have implemented the following code to generate a unique id which is not in the table.
//sql library
const mysql = require('mysql');
const sql_obj = require(__dirname + '/../secret/mysql.json');
//nanoid library
const { customAlphabet } = require('nanoid');
const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const nanoid = customAlphabet(alphabet, 30);
function uniqueid(){
let found = 0;
let conn = mysql.createConnection(sql_obj);
while (found === 0){
let id = nanoid();
conn.connect(function(err){
if (err){
found = 2;
}
else{
conn.query("SELECT * FROM id WHERE value = " + mysql.escape(id),function(err,result,fields){
if (err){
found = 2;
}
else{
if (result.length === 0){
found = 1;
}
}
})
}
})
}
if (found === 2){
return {error: 1,ret: null};
}
else if (found === 1){
return {error: 0,ret: id};
}
}
console.log(uniqueid());
I knew, my implementation is wrong. Because callbacks are asynchronous in nature, the while loop never ends and hence I got the error JavaScript heap out of memory. I went through many articles in the web to sort this out, but couldn't. The main problem is that the function uniqueid should return some value, because, I am calling it from other JavaScript file.
Thanks for any help
I think best way to prevent this is using async/await.
I promisified your mySql connection. And you can send your query and values to the function.
//sql library
const mysql = require('mysql');
const sql_obj = require(__dirname + '/../secret/mysql.json');
//nanoid library
const { customAlphabet } = require('nanoid');
const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const nanoid = customAlphabet(alphabet, 30);
let db = (query, values = null) => {
return new Promise((resolve, reject) => {
let conn = mysql.createConnection(sql_obj);
conn.connect(function (err) {
if (err) {
reject(err);
}
else {
conn.query(query + values, function (err, result, fields) {
if (err) {
reject(err);
return;
}
else {
if (result.length === 0) {
resolve();
}
}
})
}
})
})
}
async function uniqueid() {
while (found === 0) {
let id = nanoid();
try {
await db("SELECT * FROM id WHERE value =", mysql.escape(id));
return { error: 0, ret: id };
} catch (error) {
return { error: 1, ret: null };
}
}
}
console.log(uniqueid());

nodejs mysql module errors

I have a nodejs module which get result from a mysql database and insert into another mysql database within a given interval. After few queries it just get stuck and throw "ER_CON_COUNT_ERROR" and says Too many connections. My module is as follows:
function get_data() {
const mysql = require('mysql');
const moment = require('moment');
var items_per_query = 1000;
let to_connection = mysql.createConnection({
host: 'localhost',
user: 'username',
password: 'pass',
database: 'todatabase'
});
let from_connection = mysql.createConnection({
host: 'localhost',
user: 'username',
password: 'pass',
database: 'fromdatabase'
});
from_connection.query("SELECT p.*, d.uniqueid as imei FROM tc_positions p left join tc_devices d on d.id = p.deviceid order by p.id desc limit " + items_per_query, function (err, result, fields) {
if (err) throw err;
var items = [];
var table_columns_list = {};
if (Object.keys(result).length > 0) {
Object.keys(result).forEach(function (key) {
var x = result[key];
table_columns_list = {
'dt_server': moment(x['servertime']).format('YYYY-MM-DD HH:MM:ss'),
'dt_tracker': moment(x['devicetime']).format('YYYY-MM-DD HH:MM:ss'),
'lat': x['latitude'],
'long': x['longitude'],
'altitude': x['altitude'],
'angle': x['course'],
'speed': x['speed'],
'params': x['attributes'],
'fix_time': moment(x['fixtime']).format('YYYY-MM-DD HH:MM:ss'),
'accuracy': x['accuracy'],
'network': x['network']
}
items.push({ 'id': x['id'], 'table_name': 'table_' + x['imei'], 'table_columns': table_columns_list });
});
}
if (items.length >=500) {
var items_to_be_removed = [];
var total_rows_inserted = 0;
for (var x = 0; x < items.length; x++) {
to_connection.query(imei_insert, function (err, results, fields) {
if (err) {
console.log(err.message);
}
else {
let createTable = " create table if not exists .... ";
to_connection.query(createTable, function (err, results, fields) {
if (err) {
console.log(err.message);
}
else {
let insert_data = "INSERT INTO .... ";
to_connection.query(insert_data, function (err, results, fields) {
if (err) {
console.log(err.message);
}
total_rows_inserted++;
items_to_be_removed.push(row_id);
if (total_rows_inserted == items.length) {
//remove data from traccar positions table that were inserted to platform
var ids = items_to_be_removed.join(",");
from_connection.query("DELETE FROM tc_positions where id IN(" + ids + ")", function (err, results, fields) {
if (err) throw err;
console.log('removed ' + total_rows_inserted + ' rows from traccar');
return get_data(); // after finish all task call the same function again
});
}
});
}
});
}
});
}
}
else {
setInterval(get_data, 15000);
}
});
}
and I just call get_data(); function to run. Is there any efficient way to run this module smoothly. I should run it 7 days 24 hours without any interruption.
You're creating a new connection to the servers each time get_data() runs, which is overwhelming them. You need to reuse connections, as for example with connection pooling.

Database not updating based on the values from API

I'm trying to update the status for every ticket in the database by fetching all the tickets from database and then passing it to the API.
The API returns me a status which I want to update against every ticket in the database.
My code looks fine to me, but the table is not being updated.
I tried console.log() for both ticketNumber as well as info.status.name, they both are printing correct values as well.
NOTE: URL is a combination of urlcomeshere/ticketNumber
something like https://api-example.com/BCA-123
connection.query(`SELECT ticket_Number FROM tickets`, function(
err,
result,
fields
) {
var totalTickets = result.length;
for (var i = 0; i < totalTickets; i++) {
ticketNumber = result[i].ticket_Number;
var infix = "urlcomeshere/";
infix += ticketNumber;
var options = {
method: "GET",
url: infix,
auth: {
username: "username comes here",
password: "password comes here"
},
headers: {
Accept: "application/json"
}
};
request(options, function(error, response, body) {
info = JSON.parse(body)["fields"];
var updateTickets = `UPDATE tickets SET status = "${info.status.name}" WHERE ticket_Number = "${ticketNumber}"`;
connection.query(updateTickets, function(err, result) {
console.log("Updated ticket Status");
});
});
}
});
Since it is you are calling an async function your application won't know when will it end or execute, and the thread might be ended before your query is executed.
Below the example i tried to separate the query function and promisify it.
Read:
Promisification
const somefunction = () => {
connection.query(`SELECT ticket_Number FROM tickets`, function(
err,
result,
fields
) {
var totalTickets = result.length;
const promises = []
for (var i = 0; i < totalTickets; i++) {
ticketNumber = result[i].ticket_Number;
var infix = "urlcomeshere/";
infix += ticketNumber;
var options = {
method: "GET",
url: infix,
auth: {
username: "username comes here",
password: "password comes here"
},
headers: {
Accept: "application/json"
}
};
promises.push(updateTicketQuery(options, body, ticketNumber))
}
await Promise.all(promises)
});
}
const updateTicketQuery = (options, body, ticketNumber) => {
return new Promise((resolve, reject) => {
request(options, function(error, response, body) {
coonst info = JSON.parse(body)["fields"];
var updateTickets = `UPDATE tickets SET status = "${info.status.name}" WHERE ticket_Number = "${ticketNumber}"`;
connection.query(updateTickets, function(err, result) {
if(err) {
reject(err)
} else {
console.log("Updated ticket Status");
resolve(result)
}
});
});
})
}

Wait for MySQL query execution in node,js

I am using mysql in node.js. And there is a nested query in it. But it does not wait for inner query to complete. I don't understand call backs nd other function. My code is like.
exports._getItems=function(req,res){
let categoryId=req.query.categoryPost;
console.log(categoryId+"re")
con.query("SELECT item_id FROM shop_products where category_id =?",[categoryId], function (err, result, fields) {
if (err) throw res.status(403);
else
{
console.log("jhcsdcshd");
var parsedResult = JSON.parse(JSON.stringify(result));
let itemsData="";
for (var i = 0; i < parsedResult.length; i++)
{
let item_id=parsedResult[i].item_id;
console.log("Item_id is"+item_id)
con.query("SELECT id,modelNo FROM items where id =?",[item_id], function async(err1, result1, fields1,callback) {
if (err1) throw res.status(403);
else
{
var parsedResult1=JSON.parse(JSON.stringify(result1));
console.log(parsedResult1)
itemsData=itemsData+parsedResult1[0].id;
console.log("dddd"+itemsData);
if(i=parsedResult.length)
{
console.log("here");
console.log("Data"+itemsData)
res.status(200).send(itemsData);
}
}
});
console.log("ppppppp"+itemsData);
}
}
});
}
I just want that if anyone can tell me that exactly how i let do the wait for inner query execution according to my code . It is very appreciated if anyone can help me. Thanks
You can not call mysql query inside for loop you have to wait for execution. Here is your solutions
exports._getItems = function (req, res) {
let categoryId = req.query.categoryPost;
console.log(categoryId + "re")
con.query("SELECT item_id FROM shop_products where category_id =?", [categoryId], function (err, result, fields) {
if (err) throw res.status(403);
else {
console.log("jhcsdcshd");
var parsedResult = JSON.parse(JSON.stringify(result));
let itemsData = "";
var promises = [];
for (var i = 0; i < parsedResult.length; i++) {
let item_id = parsedResult[i].item_id;
console.log("Item_id is" + item_id);
promises.push(runQuery(con, item_id))
}
Promise.all(promises)
.then((data) => {
for (var i = 0; i < data.length; i++) {
var parsedResult1 = JSON.parse(JSON.stringify(data[i]));
console.log(parsedResult1)
itemsData = itemsData + parsedResult1[0].id;
console.log("dddd" + itemsData);
if (i = parsedResult.length) {
console.log("here");
console.log("Data" + itemsData)
res.status(200).send(itemsData);
}
}
})
.catch((error) => {
throw res.status(403);
})
}
})
}
function runQuery(con, item_id) {
return new Promise((resolve, reject) => {
con.query("SELECT id,modelNo FROM items where id =?", [item_id], function (err1, result1) {
if (err1) {
reject(err1);
} else {
resolve(JSON.parse(JSON.stringify(result1)));
}
})
});
}