How to access Local variables outside - javascript

I have a piece of code that needs to do the following :
For each Sensor objects in the array, get the Template ID first.
Search the Template Schema DB, get the zipcode of the corresponsing Template ID got.
From the zipcode, generate the URI
Make the requestAPI call
Get the output of the API and store it in the DB for that sensor object.
I am having problem with step 5, storing the result in the DB for each SenObject. I guess the problem is since newSensorObjectRes is defined locally in the test(), it can't be used outside. How else can I store the results for each object?
var arr = [];
function SenObj (id)
{
this.Objnum = 10;
this.Template = id;
this.Type = "AirFlow";
this.UserID = "Jessi";
}
// To store the results from the AIR API
var sensorResults = new Schema({
//reqId: {type: Number, required: true, unique: true},
//sensorId: {type: Number},
SenObj: {type: Number},
status: {type: String, default: 'Undefined'}
})
var SensorObjectRes = connUserSensors.model('SensorObjectRes', sensorResults)
//API:To create Sensor Objects when user requests for template
// When user makes a request to create a new Template,we get the tempate ID he has requested.
// We use the ID to create a Sensor Object.We might need the request id too here ??
// The array arr[] holds all the sensor obects..
app.get('/ProvisionTemplate/:id', function (req, res) {
var id = req.params.id;
console.log("Server recieved a GET /ProvisionTemplate/" + id + " request");
Template.findOne({templateId: parseInt(id)},function (err, data) {
if (err) return console.error(err);
console.log(data);
res.json(data);
// Create an Object here
var user1 = new SenObj(id);
console.log(user1.UserID);
arr.push(user1);
});
});
console.log("The array objects are :");
for (i = 0; i < arr.length; i++)
{
console.log(arr[i]);
}
var output = ""
function test()
{
var zip = "";
console.log("Interval reached");
for (i = 0; i < arr.length; i++)
{
// For each Sensor objects in the array, get the Template ID first.
// Search the Template Schema DB, get the zipcode of the corresponsing Template ID got.
// From the zipcode, generate the URI
// Make the requestAPI call
// Get the output of the API and store it in the DB for that sensor object.
console.log(arr[i]);
console.log(arr[i].Template);
var tem = arr[i].Template;
Template.findOne({templateId: tem},function (err, data)
{
if (err) return console.error(err);
console.log(data.zipcode);
zip = data.zipcode;
var uri_1 = "http://www.airnowapi.org/aq/observation/zipCode/current/?format=application/json&zipCode=";
var uri_2 = "&distance=25&API_KEY=1035C2AC-CDB8-4540-97E4-0E8D82BA335A";
var url = uri_1 + zip + uri_2;
console.log(url);
requestApi(url, function (error, response, body)
{
if (!error && response.statusCode == 200)
{
console.log(body);
//console.log(arr[i])
var newSensorObjectRes = new SensorObjectRes({"SenObj": 1 ,"status": body});
newSensorObjectRes.save(function (err, data)
{
if (err) return console.log("error updating");
console.log(data);
})
}
})
});
}
}
var interval = setInterval(test, 10000);
newSensorObjectRes.find(function (err, data)
{
if (err)
{
console.log("Could not find EC2Server db");
return;
}
console.log(data)
})

I believe the issue is having a for loop in your test function. You could be making all your Template requests before you get a response. Try using recursion instead. This will assure that your requests are made in an orderly fashion. Something like this...`
function test(i)
{
if(i == arr.length){
console.log("done");
return;
}
var zip = "";
console.log("Interval reached");
console.log(arr[i]);
console.log(arr[i].Template);
var tem = arr[i].Template;
Template.findOne({templateId: tem},function (err, data)
{
if (err) return console.error(err);
console.log(data.zipcode);
zip = data.zipcode;
var uri_1 = "http://www.airnowapi.org/aq/observation/zipCode/current/?format=application/json&zipCode=";
var uri_2 = "&distance=25&API_KEY=1035C2AC-CDB8-4540-97E4-0E8D82BA335A";
var url = uri_1 + zip + uri_2;
console.log(url);
requestApi(url, function (error, response, body)
{
if (!error && response.statusCode == 200)
{
console.log(body);
var newSensorObjectRes = new SensorObjectRes({"SenObj": 1 ,"status": body});
newSensorObjectRes.save(function (err, data)
{
if (err) return console.log("error updating");
console.log(data);
test(i+1);
})
}
})
});
}
test(0);

Related

Syntax Error when using multiple parameter substitutions in a MYSQL Query

I need to Update MYSQL data using JS after I receive an AJAX Post request
I made a variable for the MYSQL Update Query and I'm passing in the field to be updated, new value, row to be updated as an array. But for some reason those variables are read with single quotes(') which, I believe, is causing me a syntax error.
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var MYSQL = require('mysql');
var server = require('http').createServer(app);
//declaring var 'conn' for MYSQL.createPool
let columns = new Array();
// Piece of code Starting the Server
// Routing
app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
app.use(express.static(path.join(__dirname, 'public')));
app.post('/', function (req, res) {
updateWorkbook(req.body);
res.send('Thanks for the data.');
});
//This is the function extracts the row, field value that need to be updated from the AJAX request
function updateWorkbook( data ){
getcolumns().then( function (columns) {
console.log("Columns got returned to Updateworkbook function")
for (let d = 0; d < data.length; d++) {
let rowToUpdate = data[d].id.replace('row_', '').split('_')[0];
let fieldToUpdate = data[d].id.replace('row_', '').split('_')[1];
let newValue = data[d].value;
console.log('row,field,value: ' + rowToUpdate + '|' + fieldToUpdate + '|' + newValue);
let key_to_replace;
for(let i = 0; i < columns.length; i++) {
let looper = columns[i].toLowerCase()
if (looper === fieldToUpdate) {
key_to_replace = columns[i]
}
}
let field_to_replace = key_to_replace.toString();
console.log(field_to_replace) //It prints out a normal string value here
updatemysql(field_to_replace, newValue, rowToUpdate);
}
});
};
//This is the function which updates MYSQL data
function updatemysql(field, newval, row) {
var sql = "UPDATE mydb.mytable SET ? = ? WHERE ROW_ID = ?;";
conn.getConnection( function (err, connection) {
if (err){
return cb(err);
connection.release();
}
console.log("Connection got established")
conn.query(sql, [field, newval, row], function (error, results){
if (error){
throw error;
connection.release();
}
console.log('Data Updated');
connection.release();
});
});
}
//Function to extract all columns from MYSQL and stores them in an array
function getcolumns() {
return new Promise(function(resolve, reject) {
console.log("getcolumns got initiated")
conn.getConnection( function (err, connection) {
if (err){
return cb(err);
connection.release();
return reject(err);
}
else {
var sql = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'mydb' AND TABLE_NAME = 'mytable';"
conn.query(sql, function (error, results){
for (let i = 0; i < results.length; i++) {
columns.push(results[i]['COLUMN_NAME'])
}
resolve(columns);
console.log("Extracted columns")
connection.release();
});
}
});
});
};
Here's the error I receive:
Error: ER_PARSE_ERROR: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''Source_of_Phone_Number_' = 'Test' WHERE ROW_ID = '1'' at line 1`
Source_of_Phone_Number_ is the key_to_replace.
Test is the newValue.
1 is the Row_ID.
There is a problem in function updatemysql(), which uses the following SQL :
var sql = "UPDATE mydb.mytable SET ? = ? WHERE ROW_ID = ?;";
You cannot pass a column name as a parameter.
You would need to change this to :
var sql = "UPDATE mydb.mytable SET " + field + " = ? WHERE ROW_ID = ?;";
Accordingly, only two parameters should be passed to the query :
conn.query(sql, [newval, row], function (error, results){ ... });

how to call an array which is in a function from the another function in javascript?

This is the async function:
async function getpackages(conn, childId, callback) {
var childId = childId;
var request6 = new sql.Request(conn);
var packageQuery = "select OrderId,ChildID from dbo.tbl_Scheduler where NoOfMealsLeft>0 and ChildId=" + childId;
await request6.query(packageQuery, function (err, packagelist) {
if (!err && packagelist.recordsets.length > 0) {
console.log("Error:" + err + "Result:" + util.inspect(packagelist.recordsets[0]));
var orderdetail_ = [];
for (i = 0; i < packagelist.recordsets[0].length; i++) {
orderdetail_.push(packagelist.recordsets[0][i].OrderId);
}
console.log("-->" + orderdetail_);
callback(null, packagelist.recordsets[0]);
} else if (packagelist.recordsets.length < 1) {
callback("Not a valid id input", null);
}
});
};
I need to call the orderdetails_ array in the query. The array contains four data and I need to iterate over 4 data one by one, using the or in the SQL query.
module.exports.newscheduledmeal = function (req, res, next, callback) {
let entered_date = req.query.date;
let childId = req.query.id;
let current_date = new Date().toISOString().slice(0, 10);
if (entered_date < current_date) {
return callback('Please enter date more than or equal to current date.', null);
} else
var conn = new sql.ConnectionPool(dbConfig);
try {
conn.connect().then(function () {
var request = new sql.Request(conn);
getpackages(conn, childId, function (err, orderid) {
if (err) {
callback(err, null);
} else
var PackageidQuery = "select PackageId from dbo.tbl_Order where OrderId=";
request.query(PackageidQuery, function (err, packagelist) {
if (!err) {
conn.close();
callback(null, packagelist.recordsets);
} else {
conn.close();
callback("Error", null);
}
});
});
});
} catch (err) {
console.log("Exception occured:" + err);
conn.close();
callback(err, null);
}
};
I want to get the details of the array which is in getpackages to be used in the module section and specifically in the SQL query section.

Request in NodeJS async waterfall return undefined

I'm pretty new to async on node js. I use the waterfall method while parsing a xml file like this:
$('situation').each( function(){
var situation = [];
$(this).find('situationRecord').each( function(i){
var record = this;
async.waterfall([
function (callback){
var filter = {
startLocationCode: $(record).find('alertCMethod2SecondaryPointLocation').find('specificLocation').text(),
endLocationCode: $(record).find('alertCMethod2PrimaryPointLocation').find('specificLocation').text(),
overallStartTime: $(record).find('overallStartTime').text(),
overallEndTime: $(record).find('overallEndTime').text()
}
callback(null, filter, record);
},
function (filter, record, callback){
var timestamp = new Date().toDateInputValue();
var startDbResponse = 0;
var endDbResponse = 0;
if((filter.startLocationCode != '') && new Date(timestamp) >= new Date(filter.overallStartTime) && new Date(timestamp) <= new Date(filter.overallEndTime) ){
startDbResponse = locationCodeToGeodataRequst.geodataByLocationcode(filter.startLocationCode);
endDbResponse = locationCodeToGeodataRequst.geodataByLocationcode(filter.endLocationCode);
}
console.log("startDbResponse: ", startDbResponse);
console.log("endDbResponse: ", endDbResponse);
callback(null, filter, record, startDbResponse, endDbResponse);
},
function (filter, record, startDbResponse, endDbResponse, callback){
console.log("startDbResponse: ", startDbResponse);
console.log("endDbResponse: ", endDbResponse);
var situationRecord = createSituationRecord($, record, filter.startLocationCode, filter.endLocationCode, startDbResponse, endDbResponse);
console.log(situationRecord);
},
function (situationRecord, callback){
situation[i] = { situationRecord };
}
],
function(err, results){
console.error("There was an error by filtering the xml file");
console.error(err);
});
})
if(situation.length > 0){ //if situation is not empty
locations.push(situation);
}
})
console.log(locations);
}
In this part of the waterfall I make a request to my database with locationCodeToGeodataRequst.geodataByLocationcode(filter.startLocationCode); but startDbResponse and endDbResponse is undefined :
....
function (filter, record, callback){
var timestamp = new Date().toDateInputValue();
var startDbResponse = 0;
var endDbResponse = 0;
if((filter.startLocationCode != '') && new Date(timestamp) >= new Date(filter.overallStartTime) && new Date(timestamp) <= new Date(filter.overallEndTime) ){
startDbResponse = locationCodeToGeodataRequst.geodataByLocationcode(filter.startLocationCode);
endDbResponse = locationCodeToGeodataRequst.geodataByLocationcode(filter.endLocationCode);
}
console.log("startDbResponse: ", startDbResponse);
console.log("endDbResponse: ", endDbResponse);
callback(null, filter, record, startDbResponse, endDbResponse);
},
....
The request by it self works because a console.log in the request module show the correct data. So I don't understand why its undefined.
This is the request module:
exports.geodataByLocationcode = function geodataByLocationcode(locationcode){
let sql = "SELECT * FROM tmc WHERE LOCATION_CODE = " + locationcode;
let query = db.query(sql, (err, result) =>{
if(err == null){
//console.log(result);
return result;
}else{
console.log("Error by getting item from db: " + err);
throw err;
}
});
}
This is a snipped of the console.log:
....
startDbResponse: undefined
endDbResponse: undefined
startDbResponse: undefined
endDbResponse: undefined
startDbResponse: 0
endDbResponse: 0
startDbResponse: 0
endDbResponse: 0
[]
//here comes the output of the requests as json objects
....
move the console log to the last function of async. As Manjeet pointed out async takes time and console prints early.
function (situationRecord, callback){
situation[i] = { situationRecord };
if(situation.length > 0){ //if situation is not empty
locations.push(situation);
}
})
console.log(locations);
}
}

display Json in html+node.js

I need to display in a html page the results of a GET request to a mysql database which are given in JSON format. I am using express js with bootstrap and I am basically asking how to display the results of a GET request done in node.js in a html page.
This is the code that performs the GET request, tell me if I have to be more clear please
app.route('/zigbee/:action').get(function (req, res) {
var connectionZ = mysql.createConnection({
host : 'localhost',
user : '',
password : '',
database : 'ZigBeeNetwork'
});
connectionZ.connect();
if (req.param('action') == 'zi') {
//route utilizzata per inserire dati, la data รจ inserita automaticamente tramite la funzione Date()
name = req.param('name');
temp = req.param('temp');
hum = req.param('hum');
date = Date();
if(!name){name = null;}
if(!temp){temp = null;}
if(!hum){hum = null;}
var queryString = 'INSERT INTO ZigBeeTH (id, Arduino, Temp, Hum, Data) VALUES (NULL, "'+name+'", '+temp+', '+hum+', "'+date+'")';
connectionZ.query(queryString, function(err, rows, fields) {
if (err) throw err;
else{
console.log('Query performed');
res.send('Query performed');
}
});
}
if (req.param('action') == 'zs') {
//route per cercare dei dati basandosi su nome e temperatura
name = req.param('name');
temp = req.param('temp');
hum = req.param('hum');
date = Date();
var app='';
if (name) {
app += 'Arduino="'+name+'"';
}
if(temp) {
if(app) {
app+=' AND ';
}
app += 'Temp="'+temp+'"';
}
if(hum){
if(app) {
app+=' AND ';
}
app += 'Hum="'+hum+'"';
}
var queryString = 'SELECT * FROM ZigBeeTH WHERE '+app;
console.log('Test '+queryString );
connectionZ.query(queryString, function(err, rows, fields) {
if (err) throw err;
var JSONObject = JSON.stringify(rows);
res.send(JSONObject);
});
}
});

How to use global error handling code in node.js for entire api call

I have a api call which has more than one functions. Instead of applying error-handling for each and every method, is it possible to use global error handling code that send the error to UI developers.
The code is given below:
app.post('/billing/pricingdetails', function (req, res) {
console.log('pricing api called');
var workload = req.body;
var resourcelevelPricing = {};
var response = {};
var workloadinfo = {
workloadId: workload.workloadId,
ownerId: workload.ownerId,
uniqueName: workload.uniqueName,
name: workload.name
}
var pricing = {}
var allresourceIdentifiers;
if (workload.elements && workload.elements.length > 0) {
var elementlevelpricingSummary = {};
var elementArray = [];
var allresourceIdentifierArray = [];
var elementinfo = {};
var metadataModified = {};
var elementsParam = workload.elements;
// handle configurable resource
var configurableElementarray = [];
// create array of all the elements in workloadjson - to be used for resourcelevel (instance/image), charamountunitlevel, resourcetypelevel pricing detail
for (var index in elementsParam) {
// if condition skips the uri of configurable resources - handle configurable resource
if(!elementsParam[index].parameters.ResourceParameters)
{
allresourceIdentifierArray.push(elementsParam[index].uri);
if (elementsParam[index].parameters.imageUri) {
allresourceIdentifierArray.push(elementsParam[index].parameters.imageUri);
}
}
}
var allresourceIdentifiers = allresourceIdentifierArray.join(',');
// call the functionalities that gives the each level of pricing detail synchronously to construct the workload json
async.series([
function (callback) {
getpricingSummary(elementsParam, function (err, workloadinfo) {
if(err){
}
else
{
callback(null, workloadinfo);
}
});
},
function (callback) {
getPricingforResourceIdentifiers(allresourceIdentifiers, function (err, pricingDetail) {
pricing.resourceLevel = pricingDetail;
callback(null, pricingDetail);
});
},
function (callback) {
getchargeamountunitlevelPricing(allresourceIdentifiers, function (err, pricingDetail) {
//merge configurable resource with concrete resource pricing details - handle configurable resource
if(configurableElementarray.length > 0)
{
var concatednatedArray = pricingDetail.concat(configurableElementarray);
var finalResult = [];
var i = concatednatedArray.reduce(function (result, o) {
var key = o.chargeAmountUnit + o.currencyCode;
if (!(key in result)) {
result.arr.push(result[key] = o);
finalResult.push(result);
}
else {
result[key].chargeAmount += Number(o.chargeAmount);
}
return result;
}, { arr: [] }).arr;
pricing.chargeamountunitLevel = i;
trace.info(i);
}
else
{
pricing.chargeamountunitLevel = pricingDetail;
}
callback(null, pricingDetail);
});
},
function (callback) {
getresourcetypelevelPricing(allresourceIdentifiers, function (err, pricingDetail) {
if(configurableElementarray.length > 0)
{
var concatednatedArray = pricingDetail.concat(configurableElementarray);
var i = concatednatedArray.reduce(function (result, o) {
var key = o.chargeAmountUnit + o.currencyCode + o.Name;
if (!(key in result)) {
result.arr.push(result[key] = o);
}
else {
result[key].chargeAmount += o.chargeAmount;
}
return result;
}, { arr: [] }).arr;
pricing.resourcetypeLevel = i;
trace.info(i);
}
else
{
pricing.resourcetypeLevel = pricingDetail;
}
callback(null, pricingDetail);
});
}
],
function (err, result) {
workloadinfo.pricing = pricing;
res.send(workloadinfo);
});
// get element level pricing summary for each elements (vm/vs) in the array within workload json - the output to be appended within metadata of workload json
function getpricingSummary(elementsParam, callback) {
async.forEachSeries(elementsParam, createResponse, function (err,result) {
return callback(null, result);
});
};
// this method called by async.forEachSeries passing each elements (vm/vs) of workload
function createResponse(elements, callback) {
var resourceIdentifierArray = [];
elementinfo = elements;
resourceIdentifierArray.push(elements.uri);
if (elements.parameters.imageUri) {
resourceIdentifierArray.push(elements.parameters.imageUri);
}
// build string of resourceIdentifier (instance/image) for input element
var resourceIdentifiers = resourceIdentifierArray.join(',');
console.log(resourceIdentifiers);
if(elements.parameters.ResourceParameters)
{
trace.info('1');
trace.info(elements.parameters.ResourceParameters);
var configJson = JSON.parse(elements.parameters.ResourceParameters);
trace.info(Number(configJson.cpuCount));
metadataModified = elements.metadata;
// TODO : Remove this hard-coding
elementlevelpricingSummary.Name = 'Hardware';
if(configJson.totalUnitPrice)
{
var chargeAmount = configJson.totalUnitPrice;
elementlevelpricingSummary.chargeAmount = Math.round(chargeAmount * 100)/100;
}
if(configJson.ChargeAmountUnit)
{
var chargeAmountUnit = configJson.ChargeAmountUnit;
elementlevelpricingSummary.chargeAmountUnit = configJson.ChargeAmountUnit;
}
if(configJson.CurrencyCode)
{
var currencyCode = configJson.CurrencyCode;
elementlevelpricingSummary.currencyCode = configJson.CurrencyCode;
}
metadataModified.pricingSummary = elementlevelpricingSummary;
configurableElementarray.push(elementlevelpricingSummary);
// delete original metadata from workload json (to be replaced by metadata containing pricing summary)
delete elementinfo.metadata;
elementinfo.metadata = metadataModified;
elementArray.push(elementinfo);
// global workloadinfo variable is appended with array of elements with its pricing summary within metadata of respective elements
workloadinfo.elements = elementArray;
return callback();
}
else
{
// Get element level pricing summary
mysql.elementlevelpricing(resourceIdentifiers, conn, function (result) {
elementlevelpricingSummary = result;
metadataModified = elements.metadata;
metadataModified.pricingSummary = elementlevelpricingSummary;
// delete original metadata from workload json (to be replaced by metadata containing pricing summary)
delete elementinfo.metadata;
elementinfo.metadata = metadataModified;
elementArray.push(elementinfo);
// global workloadinfo variable is appended with array of elements with its pricing summary within metadata of respective elements
workloadinfo.elements = elementArray;
return callback(null,workloadinfo);
});
}
};
function getPricingforResourceIdentifiers(resourceIdentifiers, callback) {
mysql.pricingDetail(resourceIdentifiers, conn, function (result) {
return callback(null, result);
});
};
function getchargeamountunitlevelPricing(resourceIdentifiers, callback) {
mysql.chargeamountunitlevelPricing(resourceIdentifiers, conn, function (result) {
return callback(null, result);
});
};
function getresourcetypelevelPricing(resourceIdentifiers, callback) {
mysql.resourcetypelevelPricing(resourceIdentifiers, conn, function (result) {
return callback(null, result);
});
};
};
});
With Express, you can install an error handler which will be called when an error occurs in any of your routes:
// somewhere at the end of your middleware/route chain
app.use(function(err, req, res, next) {
res.send(500, err.message); // or whatever you want to send back
});
It would still be best to rethrow any errors that occur in your code:
if (err) throw err;
Also, since you're using async, you can always propagate errors back to it:
if (err) return callback(err);
And handle the errors in the final callback.

Categories

Resources