Nodejs for loop with MySQL insert not functioning as expected - mysql

When I trying to Insert some data and process the result using "for Loop", iteration only complete in last cycle.
const sql4 = "insert into core_crm_job_task set ?";
for(var m = 0; req.body.jobTasks.length > m; m++){
console.log('a'+m);
let jobTask = {
ID_JOB_REGISTRY : registryId,
ID_TASK_CODE : jobCode+' '+req.body.jobTasks[m].task_code_suffix,
TASK_TYPE : req.body.jobTasks[m].task_type,
TASK_QTY : req.body.jobTasks[m].task_qty,
TASK_INSTRUMENT : req.body.jobTasks[m].task_instrument,
TASK_INSTRUMENT_ID : req.body.jobTasks[m].task_instrument_id,
REMARK : req.body.jobTasks[m].task_remark,
IS_ACTIVE: 1,
CREATED_BY: 1,
CREATED_DATE: getCurrentTime()
};
connection.query(sql4,jobTask, (err, result) => {
if (err){
console.log('b'+m);
connection.release();
}
else{
console.log('c'+m);
//some process here
}
})
}
Below shows sample output when I used an array with 3 elements.
The log with letter 'c' only print in last element. Other elements didn't complete the iteration.
a0
a1
a2
c2
But I need to do some process after each insert query. In this case it is impossible.
Please suggest some solution!

You can you can use async.eachAsync Ref
So it will execute one by one, you will get expected result
const sql4 = "insert into core_crm_job_task set ?";
async.each(req.body.jobTasks,function(obj,callback){
let jobTask = {
ID_JOB_REGISTRY : registryId,
ID_TASK_CODE : jobCode+' '+obj.task_code_suffix,
TASK_TYPE : obj.task_type,
};
connection.query(sql4,jobTask, (err, result) => {
if (err){
callback(err);
}
callback(null);
})
});

Problem solved! :)
Just Replaced for loop variable type to "let"
for(var m = 0; req.body.jobTasks.length > m; m++)
to
for(let m = 0; req.body.jobTasks.length > m; m++)

addEmojies: function (request, callback) {
//getting the inputs
var questions = request.body.question;
//if questions contains only one
if (!Array.isArray(questions)) {
questions = que = [request.body.question];
}
const mysqlConnection = mysqlPool(function (err, connection) {
connection.beginTransaction(function (err) {
if (err) {
connection.release();
if (err) { throw err; }
}
//loop trough the questions
for (var q = 0; q < questions.length; q++) {
//setting up data object for update category
var mainQuestionValues = {
CAMPAIGN_ID: questions[q].campaign_id,
MAIN_QUESTION_TITLE: questions[q].question,
CREATED_BY: session.userdata.user_id,
HAS_SUB_QUESTIONS:0,
IS_ACTIVE: 1
};
const sql = 'INSERT INTO main_question SET ?';
connection.query(sql, mainQuestionValues, function (err, result) {
if (err) {
if (err) { throw err; }
connection.release();
connection.rollback(function () {
return callback(false);
});
}
connection.commit(function (err) {
if (err) {
connection.release();
logger.error(err);
connection.rollback(function () {
return callback(false);
});
}
connection.release();
return callback(true);
});
});
}
});
});
},

Related

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());

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)));
}
})
});
}

Adding bulk data to mysql database

I have a console program where the user scans in serial numbers, and those serial numbers get added to a database.
const mysql = require('mysql2');
const read = require('readline-sync');
const conn = new mysql.createConnection(config);
conn.connect(
function(err){
if(err){
throw err;
}
else{
console.log("Connection Established");
while(1){
var sn = read.question('Scan in serial number: ');
conn.query('INSERT INTO test (serial) VALUES (?);',
[sn], function(err, results, fields){
if (err){
throw err;
}
else{
console.log("Added stuff");
}
});
}
}
}
);
When the code runs it successfully connects to the database but queries the database. It continually prompts for user input.
Alternatively, I tried storing serial numbers in an array and then loops through it adding each element, like this.
const mysql = require('mysql2');
const read = require('readline-sync');
var array = [];
var sn = " ";
while (1) {
sn = read.question('Scan in serial number, or enter "done" if finished scanning');
if (sn == "done") {
break;
}
array.push(sn);
}
conn.connect(
function (err) {
if (err) {
throw err;
}
else {
console.log("Connection Established");
array.forEach(function (sn) {
conn.query('INSERT INTO test (serial) VALUES (?);',
[sn], function (err, results, fields) {
if (err) {
throw err;
}
else {
console.log("Added stuff");
}
});
});
}
}
);
In this case, it works inconsistently. Sometimes it works fine, and other times it fails to connect and throws a timeout error. Is there a better way to accomplish this and/or am I doing something wrong?
var promises = []
function dbOp(value) {
return new Promise(function(resolve, reject) {
conn.query('INSERT INTO test (serial) VALUES (?);',
[value], function (err, results, fields) {
if (err) {
return reject(err)
}
else {
console.log("Added stuff");
resolve(results)
}
}
}
conn.connect(function(err){
if(err){
throw err;
}
else{
for (i = 0; i < array.length; ++i) {
promises.push(dbOp(array[i]));
}
}
});
Promise.all(promises)
.then((results) => {
console.log("done", results);
})
.catch((e) => {
console.log(e)
});
This might be caused by short idle timeout setting in your mysql server. client.connect() is pretty much a no-op in mysql2, it connects immediately when you call mysql.createConnection(). You can change order to establish connection only after all data is collected:
const mysql = require('mysql2');
const read = require('readline-sync');
var array = [];
var sn = ' ';
while (1) {
sn = read.question('Scan in serial number, or enter "done" if finished scanning');
if (sn == 'done') {
const conn = mysql.createConnection(config);
array.forEach(function(sn) {
conn.query('INSERT INTO test (serial) VALUES (?);', [sn], function(err, results, fields) {
if (err) {
throw err;
} else {
console.log('Added stuff');
}
});
});
}
array.push(sn);
}

How to obtain value from inner request. Function return undefined

I'm trying to get a quiz from table quizzes and after obtaining it
trying to an array of answers from table questions. But it doesn't work
I send questionDto(JSON) to this.add method, where the question I've already
added in the table and need to add answers and
var question = require('../models/question');
function Quiz() {
this.getById = function(quizId,res) {
connection.acquire(function(err, con) {
con.query('select * from quizes where `id` = ? ', quizId,
function(err, result) {
con.release();
result.questions = question.getAllByQuizId(quizId);
res.send(result);
});
});
};
question.getAllByQuizId(quizId); has to return an array of questions. Here is an implementation
function Question() {
this.getAllByQuizId = function(quizId) {
return connection.acquire(function(err, con) {
return con.query('select * from questions where `quizId` = ? ', quizId, function(err, rows) {
if (err) throw err;
con.release();
console.log(JSON.parse(JSON.stringify(rows)));
return JSON.parse(JSON.stringify(rows));
});
});
};
console.log() returns applicable value but the function return undefined
I have wasted hours to tackle. But still can't :(
You should pass a callback to handle this instead of 'return' as it has a asynchronous block in the function.
var question = require('../models/question');
function Quiz() {
this.getById = function(quizId,res) {
connection.acquire(function(err, con) {
con.query('select * from quizes where `id` = ? ', quizId,
function(err, result) {
con.release();
question.getAllByQuizId(quizId, function(err, data){
if(err) {
throw err;
} else {
result.questions = data;
res.send(result);
}
});
});
});
};
function Question() {
this.getAllByQuizId = function(quizId, callback) {
connection.acquire(function(err, con) {
con.query('select * from questions where `quizId` = ? ', quizId, function(err, rows) {
if (err) callback(err);
con.release();
console.log(JSON.parse(JSON.stringify(rows)));
callback(null, JSON.parse(JSON.stringify(rows)));
});
});
};

better way of selecting 1 to many?

I have an express.js based rest application. Please have a look on following code and suggest me what would be better way.
I want to select user and its associated images (1 user has many images).
function getUser (connection, req, res) {
var userId = req.params.id;
connection.query('SELECT * FROM user p'
+ ' WHERE p.id = ' + connection.escape(userId), function handleSql(err, rows) {
if (err){ logAndRespond(err,res); return; }
if (rows.length === 0){ res.send(204); return; }
var adId = rows[0].adId;
// load images
connection.query('SELECT id, url FROM image WHERE ad_id = ' + connection.escape(adId), function (err, imgRows) {
if (err){ logAndRespond(err,res); return; }
if (rows.length != 0){
rows[0].images = imgRows;
}
res.json({'user': rows});
connection.release();
});
});
}
You don't have to escape parameters by yourself
You don't release the connection if an error occurred
The problem now is I don't know what you want to do with selected rows. You are also checking the rows.length twice but if there weren't any records in the first query then the second one will not be executed.
function getUser(conn, req, res) {
conn.query("SELECT * FROM user p WHERE p.id = ?;", [req.params.id], function(err, rows) {
if (err) {
return logAndRespond(err, res);
}
if (!rows.length) {
return res.send(204);
}
conn.query("SELECT id, url FROM image WHERE ad_id = ?;", [rows[0].adId], function(err, imgRows) {
if (err) {
return logAndRespond(err, res);
}
if (rows.length) { // ???
rows[0].images = imgRows;
}
res.json({"user": rows});
conn.release();
});
});
}