Variable inaccessible inside callback function - javascript

I have a variable deleteFlag which is inaccessible inside a function even though the variable's scope is global.
Explanation (Pls refer my code simultaneously):
Here, I am trying to get a MongoDB collection details, the collection store a date document (result[i].date). The variable difResult stores the difference between the current date and the date fetched from MongoDB. And let's say if the value of difResult is more than a specific threshold then handle respective if-else conditions.
My if block i.e. if(difResult>20000) has a child-process, exec function and a callback function to delete MongoDB collection, now in this function I am trying to access var deleteFlag which is sort inaccessible.
Why? And how can I make is accessible inside my function?
app.js
MongoClient.connect("mongodb://localhost:27017/", {
useUnifiedTopology: true
}, function(err, db) {
if (err) throw err;
var dbo = db.db("dbName");
dbo.collection("colName").find({}).toArray(function(err, result) {
if (err) throw err;
for (var i = 0; i < result.length; i++) {
var difResult = Math.round((today - result[i].date));
var deleteFlag = result[i].date; // Declared here and should be accessbile within the function
console.log("Delete Flag " + deleteFlag.toISOString()); //Show correct value here
console.log("Result Date " + result[i].date);
if (difResult > 20000) {
var result2 = cp.exec("rm -rf /path/" + deleteFlag.toISOString(), function(error, stdout, stderr) {
if (error !== null) {
console.log('exec error: ' + error);
return res1.status(500).json({
error: "Failed!"
});
} else {
MongoClient.connect("mongodb://localhost:27017/", {
useUnifiedTopology: true
}, function(err, db) {
console.log("Delete Flag From Collection ", +deleteFlag.toISOString());
//The above console log gives NaN or null value
//Suggest that var deleteFlag is not accessible inside this callback function
if (err) throw err;
var dbo = db.db("dbName");
var myquery = {
date: deleteFlag
};
dbo.collection("colName").deleteOne(myquery, function(err, obj) {
if (err) throw err;
console.log("1 document deleted");
db.close();
});
});
}
});
} else {
console.log("Else msg");
}
}
db.close();
});
});

You don't have to call the database twice you can optimize your code and use it like this
MongoClient.connect("mongodb://localhost:27017/", {
useUnifiedTopology: true
}, function(err, db) {
if (err) throw err;
var dbo = db.db("dbName");
dbo.collection("colName").find({}).toArray(function(err, result) {
if (err) throw err;
for (var i = 0; i < result.length; i++) {
var difResult = Math.round((today - result[i].date));
var deleteFlag = result[i].date; // Declared here and should be accessbile within the function
console.log("Delete Flag " + deleteFlag.toISOString()); //Show correct value here
console.log("Result Date " + result[i].date);
if (difResult > 20000) {
var result2 = cp.exec("rm -rf /path/" + deleteFlag.toISOString(), function(error, stdout, stderr) {
if (error !== null) {
console.log('exec error: ' + error);
return res1.status(500).json({
error: "Failed!"
});
} else {
var myquery = {
date: deleteFlag
};
dbo.collection("colName").deleteOne(myquery, function(err, obj) {
if (err) throw err;
console.log("1 document deleted");
});
}
});
} else {
console.log("Else msg");
}
}
db.close();
});
});
However if for whatever reason you need to call the database twice then store deleteFlag values in an array and then access the array wherever you like

Related

Where to place the Commit block of a complex NodeJS MySQL Transaction?

I have the following code in NodeJS which works well to;
Begin a MySQL transaction;
Create an audiopost;
Update an audiopost.
Check to see if tag1 exists and if not, create it and insert into a tag table. If it does exist simply insert it to the tag table.
Commit the transaction;
But now I'd like to also check for tag2 and tag3 also.
Unfortunately, I can't figure out where and how to place the commit block
in order to keep it all as a single transaction.
If I put it just before the closing of the check for "tag1" the code won't get as far as "tag2" and "tag3". But if I put it after then the closing brackets to the connection queries are in the wrong place. Here's the code;
var mysql = require("mysql");
var express = require("express");
var connection = require("../database");
var createAudiopost = function(req, res, next){
var title = req.body.title;
var userid = req.body.userid;
var opid = req.body.opid;
var tag1 = req.body.tag1;
var tag2 = req.body.tag2;
var tag3 = req.body.tag3;
connection.beginTransaction(function(err) {
if (err) { throw err; }
connection.query('INSERT INTO ?? (title,userid,opid) VALUES (?, ?, ? )', ['audioposts',title,userid,opid], function(err, result) {
if (err) {
connection.rollback(function() {
throw err;
});
}
var audioname = userid + '-' + result.insertId + '.m4a';
var newid = result.insertId;
console.log("newid: " , newid );
connection.query('UPDATE ?? SET audioname=? WHERE audioid = ?', ['audioposts',audioname,newid], function (error, result, fields) {
if (err) {
connection.rollback(function() {
throw err;
});
}
if (tag1) {
connection.query('SELECT tagid FROM tags WHERE tagname = ?', [tag1], function (error, result, fields) {
if (err) {
connection.rollback(function() {
throw err;
});
}
const tagid1 = result[0].tagid;
if (result < 1) {
connection.query('INSERT INTO tags SET tagname = ?', [tag1], function (error, result, fields) {
if (err) {
connection.rollback(function() {
throw err;
});
}
console.log("lets see this ridiculous result", result);
const tagInsertId = result.insertId;
connection.query("INSERT INTO entitytag SET audioid = ?, tagid = ?, userid = ?", [newid, tagInsertId, userid], function (error, result, fields) {
if (err) {
connection.rollback(function() {
throw err;
});
}
connection.commit(function(err) {
if (err) {
connection.rollback(function() {
throw err;
});
}
console.log('success!');
newid = result.insertId;
res.json({
"title" : title,
"userid" : userid,
"opid" : opid,
"insertid": newid
}); //resjson success
}); //commit
}); // insert entitytags
}); // insert tags
} // if row
else {
connection.query("INSERT INTO entitytag SET audioid = ?, tagid = ?, userid = ?", [newid, tagid1, userid], function (error, result, fields) {
if (err) {
connection.rollback(function() {
throw err;
}); //err
} //err
connection.commit(function(err) {
if (err) {
connection.rollback(function() {
throw err;
});
}
console.log('success!');
res.json({
"title" : title,
"userid" : userid,
"opid" : opid,
"insertid": newid,
"tag1": tag1
}); //resjson success
}); //commit
}) // insert entitytag2
}
}); //select tagid
}//tag1
}); //update
}); //insert
}); //begin transaction
} //createaudiopost
module.exports = createAudiopost;
Any suggestions for how I can complete such a complex transaction? I basically need to repeat the entire section of if (tag1) for tag2 and tag3.

cannot read property of undefined with result of mysql

I have this problem, although I managed the value of "result", the conditional expression "if" evaluates "result" always as "! == undefined" I also tried to manage with "result! == ''" but not handles it correctly. In this case I have no results from the sql query because "ricovero.cps" is not in the database and so I wrote some code to handle this case. How should I behave in order for the "if" to work correctly?
function getIdCPS(ricovero){
console.log("getIdCPS()");
querySQL = "SELECT id FROM codici_pronto_soccorso WHERE codice ='"+ricovero.cps+"'";
console.log("querySQL="+querySQL);
try{
connection.query(querySQL, function(err, result) {
if(err)
console.log(err);
if( result === undefined){
return "";
}else{
console.log("result is defined");
console.log("result=("+result+")");
return result[0].id;
}
});
}catch(e){
console.log("try/catch error:" + e);
}
}
Just put this code and monitor on console
const getIdCPS = (ricovero) => {
try {
const errorObj = { code: 400, error: 'Wrong Input' }
if (!ricovero || !ricovero.cps) {
throw errorObj;
}
const querySQL = "SELECT id FROM codici_pronto_soccorso WHERE codice ='" + ricovero.cps + "'";
connection.query(querySQL, (err, result) => {
if (err) {
throw err;
} else if (result) {
console.log(result);
return result;
} else {
throw err;
}
});
} catch (err) {
console.error(err);
throw err;
}
};

Mongo deleting a document using an object as a value

Hello I am having issues deleting a document from MongoDb using an object
here is what I mean
const deleteTrimByName = function (db, callback) {
// Get the documents collection
const collection = db.collection(documentName)
// Insert some documents
console.log(trimNameToDelete)
collection.deleteOne({Video_trim: trimNameToDelete}, function (err, result) {
assert.equal(err, null)
assert.equal(1, result.result.n)
console.log('Removed the document')
callback(result)
})
fs.unlink('./public/videos/cut-videos/' + documentName + '/' + trimNameToDelete.trimName + '.mp4', (err) => {
if (err) {
console.log('failed to delete local image:' + err)
} else {
console.log('successfully deleted local image')
}
})
}
where trimNameToDelete evaluates to
{"trimName":"cut2","startTime":"00:00:05","endTime":"00:00:15"}
and the mongo document appears as this in the shell
{ "_id" : ObjectId("5abe67897a9b9e0933c64acd"), "Video_trim" : { "trimName" : "cut2", "startTime" : "00:00:05", "endTime" : "00:00:15" } }
the error I get is
AssertionError [ERR_ASSERTION]: 1 == 0
For technical reasons use the Id cannot be used for deleting.
Ah I found the issue, I needed to parse the trimNametoDelete, stupid mistake, I was sending the trimNametoDelete as a string.
const deleteTrimByName = function (db, callback) {
// Get the documents collection
const collection = db.collection(documentName)
console.log('>>>>>' + trimNameToDelete)
collection.deleteOne({Video_trim: JSON.parse(trimNameToDelete)}, function (err, result) {
assert.equal(err, null)
assert.equal(1, result.result.n)
console.log('Removed the document')
callback(result)
})
fs.unlink('./public/videos/cut-videos/' + documentName + '/' + JSON.parse(trimNameToDelete).trimName + '.mp4', (err) => {
if (err) {
console.log('failed to delete local image:' + err)
} else {
console.log('successfully deleted local image')
}
})
}

Unable to access data from outside the scope of function

I have a function that downloads the user input(currently named app.json) from browser(client) to the server
function downloadUpdate(callback) {
//Using formidable node package for downloading user input to server
var form = new formidable.IncomingForm();
form.on('fileBegin', function(name, file) {
file.path = "app.json";
});
form.parse(req, function(err, fields, files) {
res.writeHead(200, {
'content-type': 'text/plain'
});
res.write('received upload:\n\n');
res.end(util.inspect({
fields: fields,
files: files
}));
});
form.on('end', function() {
callback(null);
});
}
I have another function that takes the file downloaded above and converts it into required format(final.json) something like this.
function UpdateCode(callback) {
var obj = fs.readFileSync('app.json', 'utf8');
console.log(abc); //Im getting undefined here
var object = JSON.parse(obj);
var data2 = [];
for (var j = 0; j < object.length; j++) {
if (object[j].value == `${abc}`) {
data2.push(object[j]);
}
}
console.log(data2);
fs.appendFile('final.json', JSON.stringify(data2), function(err) {
if (err) throw err;
console.log('Saved!');
callback(null);
});
}
I used async series function to make them run in an order like this
async.series([
downloadUpload,
UpdateCode
], function(err, result) {
if (err) throw err;
else {
console.log(result);
}
});
All of this code is inside a post request. I'm getting abc from the server
app.post('/', function(req,res){
var abc = req.body.abc;
console.log(abc); //I'm getting abc here
function downloadfile(callback){
//here goes the downloadfile definition
}
function UpdateCode(){
//upload code function
}
//now i call async.series method
async.series([
downloadUpload,
UpdateCode
], function(err, result) {
if (err) throw err;
else {
console.log(result);
}
});
});
the thing is the value of abc is not going to function UploadCode and when I console log abc, I get undefined. Where am I going wrong?

I can't stop the asynchronous

So I am trying to get an array with a loop and the asynchronous nature of nodejs is killing me. Here is my code:
getDevices(userIDs, function(result) {
if (result) {
sendNotification(messageUser, messageText, result);
res.send("Success");
} else {
res.send("ERROR");
}
});
});
function getDevices(userIDs, callback) {
var userDevices = [];
var device = [];
for (var i = 0; i < userIDs.length; i++) {
searchRegisterDevices(userIDs[i], function(result) {
if (result) {
for (var j = 0; j < result.length; j++) {
device = {platform: result[j].platform, token: result[j].token};
userDevices.push(device);
}
} else {
console.log("ERROR");
}
});
}
callback(userDevices);
}
function searchRegisterDevices(userID, callback) {
MongoClient.connect(url, function(err, db) {
if (err) {
console.log(err);
} else {
console.log("We are connected");
}
var collection = db.collection('RegisteredDevices');
collection.find({userID: userID}).toArray(function (err, result) {
if (err) {
console.log("Error: " + err);
} else if (result.length) {
callback(result);
} else {
console.log('No document found');
}
db.close();
});
});
I first need to get all my devices out of my mongodb collection that match the ID in userIDs. SO userIDs is an array of IDs that are tied to devices in the collection. Once I get the device I need to get the device token out of the returned object.
So:
1) call getDevices passing an array of userIDs
2) call searchRegisterDevices with a device ID.
3) searchRegisterDevices returns an array of devices.
4) get the device token/s out of that array and push to userDevices array.
5) return userDevices array
6) call sendNotification with the array of userDevices
I know my issues, I just am having a hard time solving them
Instead of getting user device for each user you should get them using single query:
First: It will reduce number of calls
Second: It will save you to handle callbacks o/p.
For it use $in operator.
Change searchdevices method:
function searchRegisterDevices(userID, callback) {
MongoClient.connect(url, function(err, db) {
if (err) {
console.log(err);
} else {
console.log("We are connected");
}
var collection = db.collection('RegisteredDevices');
collection.find({
userID: {
$in: userIDs
}).toArray(function(err, result) {
if (err) {
console.log("Error: " + err);
} else if (result.length) {
callback(result);
} else {
console.log('No document found');
}
db.close();
});
});
}
It will return array of userdevices for passed userids.

Categories