NodeJs need to wrap function in a callback - javascript

I am still fairly new to NodeJS. I realize I need to put the following code in a callback so I can wait for the database call to finish, but I can't see how to get it to work.
I need to return my result to the parent function where marked at the bottom of this code:
exports.gtoken = function(req, sfinfo) {
var outcome = {};
req.app.db.models.Account.findById(req.user.roles.account.id, 'isVerified extraemail search memberid name').exec(function(err, account) {
if (err) {
return console.error(err + 'issue');
}
outcome.account = account;
var memberid = JSON.stringify(outcome.account);
var g = (new Date().getTime())/1000;
var n = (g + 86400);
var memberid = outcome.account.memberid;
var secondaryemails = outcome.account.extraemail;
var isVerified = outcome.account.isVerified;
var IDName = outcome.account.name;
var payload = {
"email": req.user.email ,
"exp": n,
"iss": req.app.locals.issid ,
"userid": req.user.id ,
"signedin": 'true' ,
"memberid": memberid ,
"secondaryemails": secondaryemails ,
"isVerified": isVerified ,
"IDName": IDName ,
"sfinfo": sfinfo,
};
var token = jwt.encode( payload, req.app.config.cryptoKey, 'HS512' );
console.log(token);
return token;
});
// I need to return my result here to the parent function
};

Without more details, it's difficult to guess what this method is doing and what value do you expect to be returned.
I believe, however, you're trying to get the token with this method. So here's what you might be looking for:
exports.gtoken = function(req, sfinfo, callback) {
req.app.db.models.Account.findById(req.user.roles.account.id, 'isVerified extraemail search memberid name').exec(function(err, account) {
if (err) {
callback(err, null);
} else {
var outcome = {};
outcome.account = account;
var memberid = JSON.stringify(outcome.account);
var g = (new Date().getTime()) / 1000;
var n = (g + 86400);
var memberid = outcome.account.memberid;
var secondaryemails = outcome.account.extraemail;
var isVerified = outcome.account.isVerified;
var IDName = outcome.account.name;
var payload = {
"email": req.user.email,
"exp": n,
"iss": req.app.locals.issid,
"userid": req.user.id,
"signedin": 'true',
"memberid": memberid,
"secondaryemails": secondaryemails,
"isVerified": isVerified,
"IDName": IDName,
"sfinfo": sfinfo,
};
var token = jwt.encode(payload, req.app.config.cryptoKey, 'HS512');
callback(null, token);
}
});
};
And here's how you could use the method:
gtoken(req, sfinfo, function(err, token) {
if (err) {
console.error(err + 'issue');
} else {
console.log(token);
}
});

Related

Searching two tables in one function in DynamoDB

I am trying to link two tables in DynamoDB for an Amazon Alexa skill. I am using two tables one is named 'yesno' and the other 'fixtures'. The fixtures table has a list of 22 names in each record and these names are in the 'yesno' table along with the column 'goals'. Here you can see the tables in more detail. Name Table:
Fixtures Table:
As you can see there are names that link the two databases together. I use the team1 column to search the fixtures table and use the name column to search the name table. Here is my code for searching:
function readDynamoItem(params2, callback) {
var AWS = require('aws-sdk');
AWS.config.update({region: AWSregion});
var dynamodb = new AWS.DynamoDB();
const names = new Array();
console.log('reading item from DynamoDB table');
dynamodb.scan(params2, function (err, data){
if (err) console.log(err, err.stack); // an error occurred
else{
console.log(data); // successful response
//tried to put a automatic loop for the long bit of code after this but didnt work so anyone with insight on this too would be helpful
/*for(var i = 1; i <= 11; i++){
var str = "T1S";
var pos = i.toString();
pos = str.concat(pos);
names[i] = jsonToString(data.Items[0].pos);
}
for(var j = 1; j <= 11; j++){
str = "T2S";
pos = j.toString();
pos = str.concat(pos);
names[(j+11)] = jsonToString(data.Items[0].pos);
}
*/
names[1] = jsonToString(data.Items[0].T1S1);
names[2] = jsonToString(data.Items[0].T1S2);
names[3] = jsonToString(data.Items[0].T1S3);
names[4] = jsonToString(data.Items[0].T1S4);
names[5] = jsonToString(data.Items[0].T1S5);
names[6] = jsonToString(data.Items[0].T1S6);
names[7] = jsonToString(data.Items[0].T1S7);
names[8] = jsonToString(data.Items[0].T1S8);
names[9] = jsonToString(data.Items[0].T1S9);
names[10] = jsonToString(data.Items[0].T1S10);
names[11] = jsonToString(data.Items[0].T1S11);
names[12] = jsonToString(data.Items[0].T2S1);
names[13] = jsonToString(data.Items[0].T2S2);
names[14] = jsonToString(data.Items[0].T2S3);
names[15] = jsonToString(data.Items[0].T2S4);
names[16] = jsonToString(data.Items[0].T2S5);
names[17] = jsonToString(data.Items[0].T2S6);
names[18] = jsonToString(data.Items[0].T2S7);
names[19] = jsonToString(data.Items[0].T2S8);
names[20] = jsonToString(data.Items[0].T2S9);
names[21] = jsonToString(data.Items[0].T2S10);
names[22] = jsonToString(data.Items[0].T2S11);
}
});
var goals = new Array();
//for loop to be used later when expanding
//for(var i = 1; i <= 22; i++){
var params = {
TableName: 'yesno',
FilterExpression: 'name = :value',
ExpressionAttributeValues: {':value': {"S": names[2]}}
};
dynamodb.scan(params, function (err, data) {
if (err) console.log(err, err.stack); // an error occurred
else{
console.log(data); // successful response
var temp = jsonToString(data.Items[0].goals);
goals[1] = temp;
}
callback(goals[1]);
});
//}
}
function jsonToString(str){
str = JSON.stringify(str);
str = str.replace('{\"S\":\"', '');
str = str.replace('\"}', '');
return str;
}
I am trying to use the goals array to print each persons goals off but right now it won't even print one persons and instead will print an undefined object of some sort. I'm guessing it just can't search the names table using the names array. The main bit of code I am having a problem with is when searching the yesno table as you can see in this code:
var goals = new Array();
//for loop to be used later when expanding
//for(var i = 1; i <= 22; i++){
var params = {
TableName: 'yesno',
FilterExpression: 'name = :value',
ExpressionAttributeValues: {':value': {"S": names[2]}}
};
dynamodb.scan(params, function (err, data) {
if (err) console.log(err, err.stack); // an error occurred
else{
console.log(data); // successful response
var temp = jsonToString(data.Items[0].goals);
goals[1] = temp;
}
callback(goals[1]);
});
//}
I know for sure there is nothing wrong with the implementation but here it is just in case it is helpful:
const handlers = {
'LaunchRequest': function () {
this.response.speak('welcome to magic answers. ask me a yes or no question.').listen('try again');
this.emit(':responseReady');
},
'MyIntent': function () {
var MyQuestion = this.event.request.intent.slots.MyQuestion.value;
console.log('MyQuestion : ' + MyQuestion);
const params2 = {
TableName: 'Fixtures',
FilterExpression: 'team1 = :value',
ExpressionAttributeValues: {':value': {"S": MyQuestion.toLowerCase()}}
};
//const params3 = {
// TableName: 'Fixtures',
// FilterExpression: 'team2 = :value',
// ExpressionAttributeValues: {':value': {"S": MyQuestion.toLowerCase()}}
//};
readDynamoItem(params2, myResult=>{
var say = MyQuestion;
say = myResult;
say = 'The top scorer for ' + MyQuestion + ' is ' + myResult;
this.response.speak(say).listen('try again');
this.emit(':responseReady');
});
},
'AMAZON.HelpIntent': function () {
this.response.speak('ask me a yes or no question.').listen('try again');
this.emit(':responseReady');
},
'AMAZON.CancelIntent': function () {
this.response.speak('Goodbye!');
this.emit(':responseReady');
},
'AMAZON.StopIntent': function () {
this.response.speak('Goodbye!');
this.emit(':responseReady');
}
}
;

Node.JS RemoteExec call not firing properly

Querying a database for a list of servers to perform a command on. The array is populated properly and echos out as planned, but none of the connections occur. I tried both passing the array directly into rexec and looping through a forEachAsync. Neither process the server list properly. Am I referencing the array elements improperly?
Mind the syntax errors at the end, I was just trying to include both methods I tried.
#!
var mysql = require('mysql');
var resultset = require('node-array');
var rexec = require('remote-exec');
var fs = require('fs');
var _ = require('lodash');
//var streamBuffers = require('stream-buffers');
var moment = require('moment');
var util = require('util');
var now = moment().format('YYYYMMDD_HHmmss');
var logStdout = process.stdout;
var errStderr = process.stderr;
console.log = function () {
logStdout.write(util.format.apply(null, arguments) + '\n');
}
console.error = function () {
errStderr.write(util.format.apply(null, arguments) + '\n');
}
var connection = mysql.createConnection({
host : 'abc',
user : 'user',
password : '******',
database : 'db'
});
var ssh_options = {
port: 22,
username: 'e109gh',
privateKey: fs.readFileSync('R:/nodeJS/sshkey.priv'),
stdout: fs.createWriteStream('./out.txt'),
stderr: fs.createWriteStream('./err.txt')
}
var my_conn_options = _.clone(ssh_options);
var cmds = ['hostname -i'];
connection.query('SELECT name FROM server', function(err, rows) {
rows.forEachAsync(function(element, index, array) {
console.log(element.name);
rexec(element.name,cmds,my_conn_options,function(err){
if (err) {
now = moment().format('YYYY-MM-DD HH:mm:ss');
console.error(err);
} else {
console.log("it worked for "+element.name);
}
});
});
});
// var buffer = new streamBuffers.WritableStreamBuffer();
connection.end(function(err) {});
// my_conn_options.stdout = buffer;
//
// rexec(rows,cmds,my_conn_options,function(err){
// if (err) {
// now = moment().format('YYYY-MM-DD HH:mm:ss');
// console.error(err);
// } else {
// console.log()
// }
// });
//
//});

Respond to request after all data is inserted to database

I am trying to implement multiple data insertion on one call and trigger response only after all data is inserted. This is how I am currently doing it:
create: function(req, res) {
var response = {};
var num = req.body.num;
var ret = 0;
for (var i = 0; i < num; i++) {
var db = new user();
db.enabled = false;
db.save(function(err){
if(err) {
// Handle error
} else {
ret++;
// Do something
}
});
}
response = {"status" : 200, "message" : "It's working: " + ret};
res.json(response);
}
The problem with this approach is that all the callbacks for save will be triggered after res.json(response) which is wrong because sometimes I would also like to inform user how much data was saved. User will always receive the following response:
It's working: 0
Because ret variable is always 0. It's getting increased only after response is already triggered. What am I doing wrong?
EDIT:
Code after Will's suggestion:
var Q = require('q');
create: function(req, res) {
var response = {};
var num = req.body.num;
var ret = 0;
var tasks = [];
for (var i = 0; i < num; i++) {
var db = new user();
db.enabled = false;
tasks.push(db.save());
}
Q.all(tasks).then(
function(results) {
response = {"status" : 200, "message" : "It's working!"};
},
function(err) {
response = {"status" : 500, "message" : "Not working!" };
);
res.json(response);
}
for (var i = 0; i < num; i++) {
var db = new user();
db.enabled = false;
db.save(function(err){
if(err) {
// Handle error
} else {
ret++;
if(ret == num){
response = {"status" : 200, "message" : "It's working: " + ret};
res.json(response);
}
}
});
}

How to pass parameter between two javascript files in express.js

I am using express js and i want to pass parameter from one javascript file to other. How can I achieve this??
The two files are 1. process.js
var WebPageTest = require('webpagetest');
var wpt = new WebPageTest('server address');
var data_url;
exports.process = function (req, res){
//Running the test
wpt.runTest(script,{runs: 1},function(err, data) {
console.log("<----STARTING TEST---->");
if(err){ console.log(err);}
data_url = data.data.summaryCSV;
console.log('-----------');
console.log(data_url);
console.log('-----------');
});
res.render('index.jade',{par: 'welcome to webpagetest performance, the tests are running in background.'})
};
storedata.js is here
var request = require('request');
var CSV = require('csv-string');
var moment = require('moment');
var process = require('./process.js');
exports.storedata = function(req,res){
var URL;
var loadTime;
var TTFB;
var TTFB1;
var date;
var date1;
var date2;
var db;
console.log(process.process.data_url);
request({uri:process.process.data_url,method:'GET'}, function (error,response,body) {
//console.log('----######----');
//console.log(response.headers);
console.log('----######----');
//console.log(response);
if (error) {
console.log('got an error' + error);
}
//console.log(response);
//console.log(body);
var data = body;
console.log('here is the body');
console.log('----######----');
console.log(body);
CSV.forEach(data, ',', function (row, index) {
if (index == 1 || index == 2) {
URL = row[0];
loadTime = row[1];
TTFB = row[2];
TTFB1 = parseInt(TTFB);
date = new Date(row[59] * 1000);
month = date.getUTCMonth() + 1;
month = month.toString();
var day = date.getUTCDate();
day = day.toString();
var year = date.getUTCFullYear();
year = year.toString();
date = year + "-" + month + "-" + day;
date1 = new Date(date);
date2 = moment(date1).format('YYYY-MM-DD');
//console.log(loadTime);
var app_re = new RegExp(/^https\:\/\/some-url/);
var staging_re = new RegExp(/^https\:\/\/some-url2/);
var webuinqa_re = new RegExp(/^https\:\/\/some-url3/);
// Writting into the databse for some-url
if(app_re.test(URL)){
var db = req.db;
var collection = db.get('app');
collection.insert({
"Date": date2,
"TTFB": TTFB1,
"loadTime": loadTime,
"Url": URL
}, function (err, doc) {
if (err) {
res.send("There was a problem adding the information to the database.");
}
});}
//Writting into the database for some-url2
if(staging_re.test(URL)){
var db = req.db;
var collection = db.get('staging');
collection.insert({
"Date": date2,
"TTFB": TTFB1,
"loadTime": loadTime,
"Url": URL
}, function (err, doc) {
if (err) {
res.send("There was a problem adding the information to the database.");
}
});}
//Writting into the database for some-url3
if(webuinqa_re.test(URL)){
var db = req.db;
var collection = db.get('webuinqa');
collection.insert({
"Date": date2,
"TTFB": TTFB1,
"loadTime": loadTime,
"Url": URL
}, function (err, doc) {
if (err) {
res.send("There was a problem adding the information to the database.");
}
});}
res.render('index', {title: "All the test Results have been added to the databases, Go to localhost/getData to get the graph"});
//res.redirect('/getData');
}
});
});
};
I want to pass parameter data_url in process.js file to storedata.js file so. I will use the value of data_url in method request in storedata.js.
You could try something like this:
In your storedata.js
module.exports = function(data_url) {
// ...
}
In process.js:
var request = require('request');
var CSV = require('csv-string');
var moment = require('moment');
// The path like this assumes storedata.js and process.js
// are in the same folder.
var storeData = require('./storedata');
exports.process = function (req, res){
var URL;
var loadTime;
var TTFB;
var TTFB1;
var date;
var date1;
var date2;
var db;
var data_url;
// initiating the test
var WebPageTest = require('webpagetest');
var wpt = new WebPageTest('server-address');
//Running the test
wpt.runTest(script,function(err, data) {
//console.log("hello -->",err || data);
data_url = data.data.summaryCSV;
console.log('-----------');
console.log(data_url);
console.log('-----------');
// Once your data_url is ready
storeData(data_url);
UPDATE:
Based on your comments, here is a possible solution.
var WebPageTest = require('webpagetest');
var wpt = new WebPageTest('server address');
var data_url;
exports.process = function (req, res){
//Running the test
wpt.runTest(script,{runs: 1},function(err, data) {
console.log("<----STARTING TEST---->");
if(err){ console.log(err);}
data_url = data.data.summaryCSV;
console.log('-----------');
console.log(data_url);
console.log('-----------');
});
res.render('index.jade',{par: 'welcome to webpagetest performance, the tests are running in background.'})
};
// Create another method that is able to return the saved data.
exports.getSavedDataURL = function() { return data_url; }
Then in storedata.js
exports.storedata = function(req,res){
var URL;
var loadTime;
var TTFB;
var TTFB1;
var date;
var date1;
var date2;
var db;
//
var url = process.getSavedDataURL();
request({uri:url,method:'GET'}, function (error,response,body) {

MySQL query in loop Javascript not work

I used the closures in this loop. But its only print the right data on the console log, and the sql query did not work. The inserted data on MySQL is the last variable of the loop.
I thought this is because of writing speed of MySQL. But don't know how to fix it. Any idea?
Thanks
module.exports = function (callback) {
queryGetForSend = "SELECT * FROM image WHERE send_request is NULL AND post_request is NOT NULL AND year(moderate_time) = year(curdate()) AND month(moderate_time) = month(curdate()) AND (time(moderate_time) < (curtime() - 15));";
conn.query(queryGetForSend, function(err, rows, fields){
for (i in rows) {
if (rows[i].post_request == 'approve') {
resultSend = 1
} else {
resultSend = 2
}
var fileID = rows[i].img_md5;
queryString = fileID + "=" + resultSend;
// Request url: "http://im-api1.webpurify.com/image_queue/results/?key="
var d = new Date();
Date.masks.default = 'YYYY-MM-DD hh:mm:ss';
sendTime = d.format();
(function(queryString, sendTime) {
querySent = "UPDATE image SET send_request=1,result_sent='"+queryString+"',send_time='"+sendTime+"' WHERE send_request is NULL AND post_request is NOT NULL AND year(moderate_time) = year(curdate()) AND month(moderate_time) = month(curdate()) AND (time(moderate_time) < (curtime() - 15));";
conn.query(querySent, function (err, rows, fields) {
if (err) throw err;
console.log("http://google.com?key=" + key + "&" + queryString);
});
})(queryString, sendTime);
(function(queryString){
request.get("http://google.com" + key + "&" + queryString, function(err, res, body) {
});
})(queryString);
}
// callback(rows);
});
};
Two suggestions:
Avoid concatenation in SQL queries, use placeholders or prepared statements instead (if you care about security).
Use array.forEach() instead of a regular for-loop with a closure to avoid accidental use of variables set inside the for-loop:
conn.query(queryGetForSend, function(err, rows, fields) {
if (err) throw err;
rows.forEach(function(row) {
var resultSend;
if (row.post_request == 'approve') {
resultSend = 1
} else {
resultSend = 2
}
var fileID = row.img_md5;
var queryString = fileID + '=' + resultSend;
var d = new Date();
Date.masks.default = 'YYYY-MM-DD hh:mm:ss';
var sendTime = d.format();
var querySent = 'UPDATE image SET send_request=1, result_sent=?, send_time=? WHERE send_request IS NULL AND post_request IS NOT NULL AND year(moderate_time) = year(curdate()) AND month(moderate_time) = month(curdate()) AND (time(moderate_time) < (curtime() - 15));';
conn.query(querySent, [queryString, sendTime], function (err) {
if (err) throw err;
console.log('http://google.com?key=' + key + '&' + queryString);
});
request.get('http://google.com?key=' + key + '&' + queryString, function(err, res, body) {
});
});
});

Categories

Resources