Node Js callback return function - javascript

I want to return database value in node js and pass as a variable in ejs file.
Bellow is the code, Which I used. it did not return value.
function getExternalLocation(cb) {
mssql.connect(msSqlSettings, function (err ) {
if (err) {
cb(err);
}
var getQuery = "SELECT [Title] FROM [dbo].[StyleTemplates] " ;
//console.log(getQuery);
var request = new mssql.Request();
// query to the database and get the data
request.query(getQuery, function (err, rows) {
mssql.close();
cb(err, rows);
});
});
}
exports.eejsBlock_editbarMenuLeft = function (hook_name, args, cb) {
var userData = getExternalLocation(args, function(err, rows) {});
args.content = args.content + eejs.require(
'ep_resources/templates/editbarButtons.ejs', {
userData: userData
});
return cb();
})
userData did not return any value.

var userData = getExternalLocation(args, function(err, rows) {});
I don't think userData will get right data in async function, there is no await, so you can try to get data in callback.
getExternalLocation(args, function(err, rows) {
var userData = rows;
args.content = args.content + eejs.require(
'ep_resources/templates/editbarButtons.ejs', {
userData: userData
});
});

Related

Nodejs api structure on calling sql helpers inside another helper all called by a controller

I'm studying to create a simple API with mysql. I've understood and implemented the simple structure in which the app call the router, that call the controller, that call the service. But now i'm developing a multiple tag service module and I've realized that I need to call the same sql queries services declared in it. I show you the code for a better understanding:
tag_service.js:
const mysql = require("../../config/database");
module.exports = {
insertTags: async (data, callBack) => {
const connection = await mysql.connection();
let results = '';
const tagsArray = data.tags.map(tag => [data.id_manager,data.cod_table,data.id_record,tag])
try {
//console.log("at insertCallout...");
await connection.query("START TRANSACTION");
results = await connection.query(
`INSERT INTO s_com_tags (id_manager,cod_table,id_record,tag)
VALUES (?,?,?)`,
[tagsArray]
);
await connection.query("COMMIT");
} catch (err) {
await connection.query("ROLLBACK");
//console.log('ROLLBACK at insertCallout', err);
throw err;
} finally {
await connection.release();
return callBack(null, results);
}
},
deleteTags: async (data, callBack) => {
//console.log(data);
let results = '';
const connection = await mysql.connection();
try {
//console.log("at deleteCallouts...");
await connection.query("START TRANSACTION");
results = await connection.query(
`DELETE FROM s_com_tags
WHERE cod_table = ? AND id_record = ? AND tag IN (?)`,
[data.code_table, data.id_record,data.tags]
);
//console.log(res);
await connection.query("COMMIT");
} catch (err) {
await connection.query("ROLLBACK");
//console.log('ROLLBACK at deleteCallouts', err);
throw err;
} finally {
await connection.release();
return callBack(null, Callouts);
}
},
};
controller's structure that will use the service:
module.exports = {
updateLabDesc: async (req, res, next) => {
try {
const body = req.body;
if(!body.internal_code){
updateLabDesc(body.manager, async (err, results) => {
if (err) {
return next(createError.InternalServerError())
}
});
}
updateTags(body, async (err, results) => {
if (err) {
return next(createError.InternalServerError())
}
return res.json({
success: (results ? 1 : 0 ),
message: (results || 0) + " LabDesc inserted successfully"
});
});
} catch (error) {
next(error)
}
},
};
But the update is something like
updateTag function => {
try {
const current_tags = await getTags(req.body);
let newTags = [];
let oldTags = [];
req.body.tags.forEach(tag => {
if(!current_tags.includes(tag))
newTags.push(tag)
});
await insertTags(newTags);
current_tags.tags.forEach(tag => {
if(!req.body.tags.includes(tag))
oldTags.push(tag)
});
await deleteTags(oldTags);
} catch (error) {
next(error)
}
},
Basically, the tag_service has insertTags and deleteTags but I need the updateTags to call these functions as well. The final controller will call insertTags, deleteTags and updateTags. How can I structure these calls?
It is a controller that could call 2 helpers (insertTag and deleteTags) and another helper (updateTags) that call these 2 helpers. Any ideas?

Trouble setting a players ID and Username through callback

With an HTML5 game I am developing at the moment, I get the player's username and ID through a token sent in by the client which are all stored in a database. Everything was working perfectly up until I had to actually set the values for the player.
I've been searching all over the internet for similar problems that I am facing, and have come up with nothing. I am not sure if this is a variable scope problem or if I am taking the wrong approach to doing this.
Anyways, here's both the socket.player and getUserSession function
var newUserID;
var newUsersName;
socket.player = {
id: newUserID,
x: randomInt(100,400),
y: randomInt(100,400),
username: newUsersName
}
function getUserSession(sessionKey, callback){
var sql = "SELECT * FROM game_sessions WHERE unique_key=? AND still_active=?";
var stillActive = 1;
var returnData = [];
db.query(sql, [sessionKey, stillActive], function(err, result){
if (err){
throw err;
}
var numFound = result.length;
if (numFound == 1) {
//session was found
var userID = result[0].user_id;
returnData.push(result[0].user_id);
var sql2 = "SELECT * FROM users WHERE id=?";
db.query(sql2, [userID], function(err, result){
if (err){
throw err;
}
var uName = result[0].username;
returnData.push(result[0].username);
return callback(returnData);
});
}
});
}
And the callback function:
getUserSession(data.token, function(result){
newUserID = result[0];
newUsersName = result[1];
socket.broadcast.emit('newclient',socket.player);
});
I would do something like this:
function sqlQuery(sql, params) {
return new Promise((resolve, reject) => {
db.query(sql, params, function(err, result) {
if (err) {
return reject(err);
}
return resolve(result);
});
});
}
function getUserSession(sessionKey, callback){
const sql = "SELECT * FROM game_sessions WHERE unique_key=? AND still_active=?";
const stillActive = 1;
let returnData = [];
try {
return sqlQuery(sql, [sessionKey, stillActive])
.then(result => {
if (result.length === 1) {
//session was found
const userID = result[0].user_id;
returnData.push(result[0].user_id);
const sql2 = "SELECT * FROM users WHERE id=?";
return sqlQuery(sql2, [userID])
.then(result => {
const uName = result[0].username;
returnData.push(result[0].username);
return callback(returnData);
})
}
})
} catch (err) {
//handle err
}
}
Edit: if the callback function being passed in is an aync function, you'll probably need to modify the above snippet to await it.

Node.js query INSERT callback not working as expected

Small problem when using POST and adding an INSERT. Works as below, but want to use a callball after the data has been inserted. At the moment the database is being updated. (good) but can't use the callback - I would expect this to be just below the throw error. So you could use result.insertId. Any thoughts welcome?
router.post('/group/:id', function(req, res) {
var idToken = req.params.id;
admin.auth().verifyIdToken(idToken).then(function(decodedToken) {
var userID = decodedToken.uid;
var name = encrypt(req.body.group);
getID(userID, function(result){
var ID = result;
var post = {ID:ID, name:name};
db.query('INSERT INTO cu_groups SET ?', post, function (error, results, fields) {
if (error)throw error;
//*** when I add response here get 502 bad gateway error.
});
res.sendStatus(200);
}); // depends on getID
// admin.auth cat
}).catch(function(error) {
res.sendStatus(error);
});
});
try this way :
router.post('/group/:id', function(req, res) {
var idToken = req.params.id;
admin.auth().verifyIdToken(idToken).then(function(decodedToken) {
var userID = decodedToken.uid;
var name = encrypt(req.body.group);
getID(userID, function(result){
var ID = result;
var post = {ID:ID, name:name};
db.query('INSERT INTO cu_groups SET ?', post, function (error, results, fields) {
if(error){
return res.status(500).send(error);
}
if(!error && results){
return res.status(200).send(results);
}
});
});
}).catch(function(error) {
return res.status(500).send(error);
});
});
if you want to use callback then ,create a separate function like :
var insertData = function(query,data,callback){
db.query(query, data, function (error, results, fields) {
if(error){callback(error,null);}
if(!error && results){callback(null,results);}
});
});
and call this way inside getID :
getID(userID, function(result){
var ID = result;
var post = {ID:ID, name:name};
insertData('INSERT INTO cu_groups SET ?', post, function (error,data){
if(error){
return res.status(500).send(error);
}
if(data){
return res.status(200).send(data);
}
});
});
Working code below many thanks to Saurabh Mistry. I removed the SET post and added the table fields and values explicity.
router.post('/group/:id', function(req, res) {
var idToken = req.params.id;
admin.auth().verifyIdToken(idToken).then(function(decodedToken) {
var userID = decodedToken.uid;
var name = encrypt(req.body.group);
getID(userID, function(result){
var ID = result;
// query
let query = "INSERT INTO cu_groups (ID, name) VALUES('" + ID + "','" + name + "')";
// execute query
db.query(query, (error, result) => {
if(error){
return res.status(500).send(error);
}
if(!error && result ){
return res.send(result);
}
});
}); // depends on getID
// admin.auth cat
}).catch(function(error) {
return res.status(500).send(error);
});
});

howto Node module.exports

I want to separate the code for executing mysql query in Node, so I am trying to use the Revealing Module pattern here
/* pool -create connection pool mysql*/
var sqlQuery = function (sqlString) {
var _result = pool.getConnection(function (err, connection) {
/* error handling*/
connection.query(sqlString, function (err, rows) {
console.log(this.sql);
if (!err) {
return _result = rows; <============
}
connection.release();
});
return;
});
console.log(_result);
return { recordSet : _result }
};
module.exports = sqlQuery;
How can I return rows to my app.js. the code below for calling sqlQuery is not working
var SqlQuery = require(./path/to/sqlQueryFile);
var rows = SqlQuery('pass sql here').recordSet;
console.log(row);
res.json(rows);
Your code is asynchronous, but you're calling it synchronously.
If you wanted to do it like this, you'll also need to pass a callback to SqlQuery.
/* pool -create connection pool mysql*/
var sqlQuery = function (sqlString, callback) {
var _result = pool.getConnection(function (err, connection) {
/* error handling*/
connection.query(sqlString, function (err, rows) {
console.log(this.sql);
if (!err) {
callback(rows);
}
connection.release();
});
});
};
module.exports = sqlQuery;
And then call it with:
var SqlQuery = require(./path/to/sqlQueryFile);
var rows = SqlQuery('pass sql here', function(recordSet){
console.log(recordSet);
res.json(recordSet);
});
Edit: If you're using newer versions of JavaScript, you have a few more options.
If you have access to Promises, you can do this:
function sqlQuery (sqlString) {
return new Promise((resolve, reject) => {
pool.getConnection(function (err, connection) {
if (err) { return reject(err); } // error handling
connection.query(sqlString, function (err, rows) {
if (err) { return reject(err); }
resolve(rows);
connection.release();
});
});
});
}
module.exports = sqlQuery;
And then you'd use it like:
var SqlQuery = require(./path/to/sqlQueryFile);
SqlQuery('pass sql here')
.then(function(recordSet) {
console.log(recordSet);
res.json(recordSet);
})
.catch(function(err) {
// do your error handling
res.status(500).json({ err: 'Sorry there was an error' });
});
If you're using even newer JavaScript, you can use the async/await syntax (currently available via Babel, and I think in FireFox. Chrome in V55).
var SqlQuery = require(./path/to/sqlQueryFile);
async handleQuery(query) {
try {
var rows = await SqlQuery(query);
res.json(rows);
} catch (e) {
console.log('Error!', e);
}
}
To chain multiple queries together:
async handleQuery(query) {
try {
return await SqlQuery(query);
} catch (e) {
console.log('Error!', e);
}
}
var rows = await handleQuery('select * from tablename');
var rowsToReturn = await handleQuery('select id from another_table where name = "' + rows[0].name + '"');

csv insert with pg library in node

So i did that kind of code.
var csv = require('csv-stream');
var request = require('request');
var fs = require('fs');
var pg = require('pg');
var conString = "pg://admin:admin#localhost:5432/labels";
// All of these arguments are optional.
var options = {
delimiter : ';', // default is ,
endLine : '\n', // default is \n,
escapeChar : '"', // default is an empty string
enclosedChar : '"', // default is an empty string
}
try {
var csvStream = csv.createStream(options);
fs.createReadStream('personss.csv').pipe(csvStream)
.on('error', function (err) {
console.error(err);
})
.on('data', function (data) {
// outputs an object containing a set of key/value pair representing a line found in the csv file.
console.log(data);
pg.connect(conString, function (err, client, done) {
client.query(
'INSERT into test (firstname, lastname) from',
function (err, result) {
if (err) {
console.log(err);
} else {
console.log('data inserted');
}
});
});
});
} catch (e) {
console(e.message);
};
where i stream the csv file with csv-stream library, how i can insert now that values from variable 'data' to my database? Should i do it by for cycle?
Update
added for cycle to iterate data
pg.connect(conString, function (err, client, done) {
for (var i = 0; data.length; i++) {
client.query(
'INSERT into test (firstname, lastname)',
function (err, result) {
if (err) {
console.log(err);
} else {
console.log('data inserted' + result.data[0]);
}
});
};
});

Categories