Javascript function callback variable scope - javascript

I am trying to pass an object variable to a callback
var sql = require('mssql');
var asset_update = function (connection, addr) {
this.connection = connection;
this.addr = addr;
this.addr_long = parseInt(addr, 16);
}
asset_update.prototype.getFromMac = function () {
var ps = new sql.PreparedStatement(this.connection);
ps.input('addr', sql.Binary);
ps.prepare('SELECT asset_id FROM asset_addr WHERE addr = #addr', function (err) {
ps.execute({ addr: this.addr_long }, function (err, recordset) {
ps.unprepare();
console.log(recordset.length);
console.log(this.addr_long);
})
});
}
How can I pass this.addr_long to the ps.execute() callback?

You can use an arrow function to preserve this :
ps.prepare('SELECT asset_id FROM asset_addr WHERE addr = #addr', (err) => {
ps.execute({ mac: this.addr_long }, function (err, recordset) { //this has been preserved
ps.unprepare();
console.log(recordset.length);
console.log(this.addr_long);
})
});
Check out this doc for the ES5 alternatives, which you shouldn't use anymore.
A popular one would be to rename this to that or self. But this is now obsolete. It would look like :
var self = this;
ps.prepare('SELECT asset_id FROM asset_addr WHERE addr = #addr', function (err) {
ps.execute({ mac: self.addr_long }, function (err, recordset) {
ps.unprepare();
console.log(recordset.length);
console.log(that.addr_long);
})
});
As you're new to node/JS, I suggest you read the following resources :
What does "this" mean?
Callbacks overview and tricks

asset_update.prototype.getFromMac = function () {
var that = this;
var ps = new sql.PreparedStatement(this.connection);
ps.input('addr', sql.Binary);
ps.prepare('SELECT asset_id FROM asset_addr WHERE addr = #addr', function (err) {
ps.execute({ mac: that.addr_long }, function (err, recordset) {
ps.unprepare();
console.log(recordset.length);
console.log(that.addr_long);
})
});
}

Related

How to perserve array value after multiple async callback in node js?

I am trying to execute multiple callback and at the same time storing value in array , but at the end array return empty.
Here is my code :
var sheetData = [];
async.forEachSeries(req.body.data, function (data, cb) {
sheet.find({accountid: req.body.id}, function (err, doc) {
if (doc == '') {// get the next worksheet and save it
var sheet = new sheet({
accountid: req.body.id,
sheetid: data.sheetid
});
var jsonData = {};
jsonData.sheetid = data.sheetid;
sheet.save(function (err, doc) {
if (!err) {
sheetData.push(jsonData); // trying to push in array , success
console.log("-----sheet data---- : ", sheetData);// data available here
}
});
}
});
cb();
}, function () {
console.log("-----sheet data---- : ", sheetData);// empty array
});
Where I am doing wrong? Can anyone suggest me ?
Or, If any other alternative in nodejs.
Thanks
The callback is being called early. Try following:
var sheetData = [];
async.forEachSeries(req.body.data, function (data, cb) {
sheet.find({accountid: req.body.id}, function (err, doc) {
if (!doc) {
return cb (); //sheet exists, call back early
}
// get the next worksheet and save it
var sheet = new sheet({
accountid: req.body.id,
sheetid: data.sheetid
});
var jsonData = {};
jsonData.sheetid = data.sheetid;
sheet.save(function (err, doc) {
if (!err) {
sheetData.push(jsonData); // trying to push in array , success
console.log("-----sheet data---- : ", sheetData);// data available here
cb (); // all done, now we can call back
}
});
});
}, function () {
console.log("-----sheet data---- : ", sheetData);// lots of sheets
});

Node JS & SQL on request per connection?

I can't seem to make multiple requests from one connection to the database. It always tells me that requests can only be made from logged in state.
For example as seen in the code below: the getCarIdandOwner part of the function will fire fine. However the getChargeRate will not.
I tried combining them like so:
connection.execSqlBatch(getcarIdandOwner, getChargeRate);
However that did not work either as it told me that getChargeRate was not defined.
Using Visual Studio Community, have NPM: Underscore and Tedious (for sql) installed. Just running it as a console app for now to test.
var Connection = require('tedious').Connection;
var config = {
userName: 'user',
password: 'passs',
server: 'somewhere.database.windows.net',
options: {
encrypt: true,
database: 'db-Test',
useColumnNames: true
var connection = new Connection(config);
connection.on('connect', function (err) {
// If no error, then good to proceed.
console.log("Connected".green);
toll("******-b77c-40e0-8f26-d44e98bc7264", "be45c903-****-****-b6ba-4b2fefa3d6b0");
});
function toll(chipId, locId) {
var carId = '';
var userOwner = '';
var charge = '';
var userBalance = '';
getcarIdandOwner = new Request(`SELECT car_id, userOwner FROM Cars WHERE carChipId = '${chipId}'`, function (err) {
if (err) {
console.log(err);
}
});
getcarIdandOwner.on('row', function (columns) {
carId = columns.car_id.value;
userOwner = columns.userOwner.value;
console.log('carId: ', carId, ' userOwner: ', userOwner);
});
getcarIdandOwner.on('done', function (rowCount, more) {
console.log(rowCount + ' rows returned');
if (rowCount = 1) {
console.log('Car Rows Returned Ok'.green);
} else {
console.log('Fatal Error: More than 1 Car Row Returned'.red);
};
});
connection.execSqlBatch(getcarIdandOwner);
getChargeRate = new Request(`SELECT Charge FROM locations WHERE location_id = '${locId}'`, function (err) {
if (err) {
console.log(err);
}
});
getChargeRate.on('row', function (columns) {
charge = columns.charge.value;
console.log('Charging account: ', userOwner, '$', charge);
});
connection.execSqlBatch(getChargeRate);
}
There is some documentation at http://tediousjs.github.io/tedious/api-connection.html which states:
Only one request at a time may be executed on a connection. Once a
Request has been initiated (with callProcedure, execSql, or
execSqlBatch), another should not be initiated until the Request's
completion callback is called.
So your code should be someting like this:
function toll(chipId, locId) {
var carId = '';
var userOwner = '';
var charge = '';
var userBalance = '';
getcarIdandOwner = new Request(`SELECT car_id, userOwner FROM Cars WHERE carChipId = '${chipId}'`, function (err) {
if (err) {
console.log(err);
} else {
getChargeRate = new Request(`SELECT Charge FROM locations WHERE location_id = '${locId}'`, function (err) {
if (err) {
console.log(err);
}
});
getChargeRate.on('row', function (columns) {
charge = columns.charge.value;
console.log('Charging account: ', userOwner, '$', charge);
});
connection.execSql(getChargeRate);
}
});
getcarIdandOwner.on('row', function (columns) {
carId = columns.car_id.value;
userOwner = columns.userOwner.value;
console.log('carId: ', carId, ' userOwner: ', userOwner);
});
getcarIdandOwner.on('done', function (rowCount, more) {
console.log(rowCount + ' rows returned');
if (rowCount = 1) {
console.log('Car Rows Returned Ok'.green);
} else {
console.log('Fatal Error: More than 1 Car Row Returned'.red);
};
});
connection.execSqlBatch(getcarIdandOwner);
}

CRON Job not working on meteor

In main.js in server folder,
I have this code,
var DDP = require('ddp');
var DDPlogin = require('ddp-login');
var Job = require('meteor-job');
var ddp = new DDP({
host: "127.0.0.1",
port: 3000,
use_ejson: true
});
Meteor.startup(() => {
var myJobs = JobCollection('myJobQueue');
Job.setDDP(ddp);
ddp.connect(function (err) {
if(err) throw err;
DDPlogin(ddp, function (err, token) {
if (err) throw err;
});
});
myJobs.allow({
admin: function (userId, method, params) {
return true;
}
});
Meteor.publish('allJobs', function () {
return myJobs.find({});
});
myJobs.startJobServer();
var workers = Job.processJobs('myJobQueue', 'sendEmail',
function (job, cb) {
console.log(job.data.text);
job.done();
cb(null);
}
);
And in my main.js in client folder,
I have this code,
var myJobs = JobCollection('myJobQueue');
var jobSub = null;
class App extends Component {
componentDidMount(){
if(jobSub !== null)
jobSub.stop();
jobSub = Meteor.subscribe('allJobs');
var job = new Job(myJobs, 'sendEmail',
{
text: 'bozo#clowns.com'
}
);
job.priority('normal')
.retry({ retries: 5,
wait: 60*1000 }) // 1 minute between attempts
.delay(0) // start immediately
.save();
}
...
render(){
console.log(myJobs.find().fetch());
...
}
}
I am using the vsivsi:meteor-job-collection package.
The problem is that console.log() is not executed.
What is wrong in my step by step installation and usage?
I need to console.log() every minute.

Undefined 'callback' with Async Waterfall / Node.js

I am trying to get a waterfall working in Node.js using Async but I keep getting the error
callback (null, articleDataSafe, req);
^
TypeError: undefined is not a function
The code is as follows
async.waterfall([
function sanitizeData (articleData, req, callback) {
articleDataSafe = sanitizeArticle(articleData);
console.log('s1');
callback (null, articleDataSafe, req);
},
function _validateData (articleDataSafe, req, callback) {
var errors = validateArticle(articleData);
var err = null;
if(errors.length > 0){
// return error messages back to the browser
err = JSON.stringify({'error': errors, "message": "fail"});
};
console.log('s2');
callback (err, articleDataSafe, req);
},
function _saveArticle (articleDataSafe, req, callback) {
// work out the tags hash
var tags = articleDataSafe['tags'];
var tagsArray = tags.split(",");
tagsArray.sort();
var tagsString = tagsArray.join();
var hashedTags = sha512(tagsString);
articleDataSafe['hashedTags'] = hashedTags;
// then save the articles
var savedArticle = saveArticle(req, articleDataSafe);
console.log('s3');
if(!savedArticle){
var err = JSON.stringify({'error': 'notSaveArticle', 'message': 'fail'});
}
callback (err, articleDataSafe);
},
function _saveTags (articleDataSafe, callback) {
var tagsDone = saveTags(articleDataSafe);
if(tagsDone.length > 0){
// return error messages back to the browser
var err = JSON.stringify({'error': tagsDone, "message": "fail"});
};
console.log('s4');
callback (err, articleDataSafe);
},
function _saveTagSets (articleDataSafe, callback) {
var tagSetsDone = saveTagSets(data);
if(tagSetsDone.length > 0){
// return error messages back to the browser
var err = JSON.stringify({'error': errors, "message": "fail"});
};
console.log('s5');
callback (err, articleDataSafe);
}
], function (error, success) {
var responseMessage = {'error': '', "message": "success"};
if (error) {
responseMessage = error;
}
res.end(JSON.stringify(responseMessage));
});
Can any explain what is going wrong. I have been trying for ages now to get it working with no luck.
Any help will be appreciated.
Thanks,
Cs1h
The first function is passed no other argument than the callback. You'd need to start like this:
async.waterfall([
function sanitizeData (callback) {
// ^^^^^^^^^^ no articleData, no req
articleDataSafe = sanitizeArticle(articleData);
console.log('s1');
callback (null, articleDataSafe, req);
},
…
However I doubt you need async at all.

How to pass scope to callback functions in nodejs?

Im using nodejs and the xml2js module. I'm reading an XML file and try to emit an event after the xml is converted to an json object. My code looks like this :
var fs = require('fs'),
util = require('util'),
events = require('events'),
xml2js = require('xml2js');
var CIRCUITMODELSFILENAME = "ControlCircuitModels.xml";
var CIRCUITPARTMODELSFILENAME = "ControlCircuitParts.xml";
var circuitModels, circuitPartModels;
function ModelController() {
if (false === (this instanceof ModelController)) {
return new ModelController();
}
events.EventEmitter.call(this);
};
util.inherits(ModelController, events.EventEmitter);
ModelController.prototype.load = function (baseDir) {
var parser = new xml2js.Parser({
normalize: true,
trim: true,
explicitArray: false
});
fs.readFile(baseDir + "/" + CIRCUITMODELSFILENAME, function (err, data) {
parser.parseString(data, function (err, result) {
circuitModels = result;
console.log('circuit models loaded');
parser.reset();
fs.readFile(baseDir + "/" + CIRCUITPARTMODELSFILENAME, function (err, data) {
parser.parseString(data, function (err, result) {
circuitPartModels = result;
console.log('circuit part models loaded');
moduleReady = true;
this.emit("modelsloaded", null);
});
});
});
});
};
// public interface
exports.ModelController = ModelController;
Problem is that the scope when emitting the event is lost.
this.emit("modelsloaded", null);
this hasn't inherited the emit from EventEmitter.
How can I pass the scope to the parser.parseString function?
Thanks
Chris
Not sure if this is the best solution, bis this works (doesn't look straight foreward):
fs.readFile(baseDir + "/" + CIRCUITMODELSFILENAME, function (err, data) {
parser.parseString(data, function (err,result) {
circuitModels = result;
parser.reset();
fs.readFile(baseDir + "/" + CIRCUITPARTMODELSFILENAME, function (err, data) {
circuitPartModels = result;
console.log('circuit models loaded');
parser.parseString(data, function (err, result) {
console.log('circuit part models loaded');
this.emit("modelsloaded", null);
moduleReady = true;
circuitPartModels = result;
}.bind(this));
}.bind(this));
}.bind(this));
}.bind(this));

Categories

Resources