Unable to access data from outside the scope of function - javascript

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?

Related

Variable inaccessible inside callback function

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

Callback is not a function -manage asynchronous call Node js

I am reading files from ftp using the code below.
var JSFtp = require("jsftp");
var config = require('./config.json');
var FtpService = function () {};
// Connect to FTP
var Ftp = new JSFtp({
host: config.ftp.host,
port: config.ftp.port,
user: config.ftp.user,
pass: config.ftp.pass
});
FtpService.prototype.getFTPDirectoryFiles = function (callback) {
Ftp.list(config.ftp.FilePath, function(err, res) {
if(err){
console.log('File Listing Failed', err);
callback(null,err);
return;
}
else{
console.log(res);
callback(null,res);
}
});
};
FtpService.prototype.closeFtp = function () {
console.log('Disconnect to FTP');
};
module.exports = new FtpService();
Now i include this ftp service js file in my index.js as
var ftp = require('./ftpservice.js');
ftpfiles = ftp.getFTPDirectoryFiles();
console.log(ftpfiles);
getFTPDirectoryFiles returns the list of file. But if i call it via index.js i get undefined ftpfiles. This is because of the asynchronous nature of node js.
so i thought of adding callback but
I am getting the error Callback is not defined in function FtpService.prototype.getFTPDirectoryFiles
In this line:
ftpfiles = ftp.getFTPDirectoryFiles()
you are not passing the callback that that function requires and are trying to use a return value that the function does not return.
You need to do something like this:
var ftp = require('./ftpservice.js');
ftp.getFTPDirectoryFiles(function(err, ftpfiles) {
if (err) {
console.log(err);
} else {
console.log(ftpfiles);
}
});
You need to pass a callbackfunction in your function getFTPDirectoryFiles();
var ftp = require('./ftpservice.js');
var ftpFiles;
function setFtpFiles(err, res) {
if (err) throw err;
ftpFiles = res; // to use "ftpFiles" variable later
console.log(res);
}
ftp.getFTPDirectoryFiles(setFtpFiles);
1 Don't change args order to call callback. (replace callback(null,err); and callback(null,res); by callback(err,res);)
2 You need define a specifc function (your callaback) an give it to ftp.getFTPDirectoryFiles().
var JSFtp = require("jsftp");
var config = require('./config.json');
var FtpService = function () {};
// Connect to FTP
var Ftp = new JSFtp({
host: config.ftp.host,
port: config.ftp.port,
user: config.ftp.user,
pass: config.ftp.pass
});
FtpService.prototype.getFTPDirectoryFiles = function (callback) {
Ftp.list(config.ftp.FilePath, function(err, res) {
if(err){
console.log('File Listing Failed', err);
callback(err, res);
return;
}
else{
console.log(res);
callback(err, res);
}
});
};
FtpService.prototype.getFTPDirectoryFilesSimplify = function (callback) {
// no console.log, but very more simple !
Ftp.list(config.ftp.FilePath, callback);
};
FtpService.prototype.closeFtp = function () {
console.log('Disconnect to FTP');
};
and then :
var ftp = require('./ftpservice.js');
ftpfiles = ftp.getFTPDirectoryFiles(function(err,res){
// do your specifc job here using err and res
});
console.log(ftpfiles);

The csvtojson converter ignores my file name and just puts undefined

Basically, when I just run csvtojson module on node.js without any code, it works perfectly. But once I put it into the function, it just comes out with undefined even though my file path is still there.
Js code:
var Converter = require("csvtojson").Converter;
// create a new converter object
var converter = new Converter({});
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost:27017/myproject';
// call the fromFile function which takes in the path to your
// csv file as well as a callback function
var woops;
var createNewEntries = function(db, woops, callback) {
converter.fromFile("./NTA-SAM-Inventory-List-Security-Management-
New_2017.csv",function(err, result){
// if an error has occured then handle it
if(err){
console.log("An Error Has Occured");
console.log(err);
}
// the result of the conversion
console.log(result);
console.log('ohhhhh');
woops=result;
});
console.log(woops);
};
MongoClient.connect(url, function(err, db) {
if(err) {
console.log(err);
}
setTimeout(function(){
createNewEntries(db, woops, function(){
if(err)
throw err;
else{
console.log(woops);
}
db.close();
});
},2000);
});
This is just testing out whether it converts inside a function and it just shows
undefined
[]
ohhhhh
without converting at all when in a function. So exactly what did I do wrong. By right it should have convert after calling the function. Does it have to do with my code executing before the function ? I already put a setTimeout just to give it some time to do so I assume it shouldn't have to do with the order of my code. Thanks in advance!
You should try below code for your file name:
__dirname + "/NTA-SAM-Inventory-List-Security-Management-
New_2017.csv"
Replace your code for converter.fromFile() , Now your code would be like that:
converter.fromFile(__dirname + "/NTA-SAM-Inventory-List-Security-Management-
New_2017.csv" ,function(err, result){
// if an error has occured then handle it
if(err){
console.log("An Error Has Occured");
console.log(err);
}
// the result of the conversion
console.log(result);
console.log('ohhhhh');
woops=result;
MongoClient.connect(url, function(err, db) {
if(err) {
console.log(err);
}
setTimeout(function(){
createNewEntries(db, woops, function(){
if(err)
throw err;
else{
console.log(woops);
}
db.close();
});
},2000);
});
});
Hope it will work for you.
If the above code are not wouking then try below code with fast-csv module:
var fcsv = require('fast-csv');
var fs = require('fs');
/**
* Get the records from csv
*/
var writeZipCodes = function () {
var stream = fs.createReadStream(__dirname + "/NTA-SAM-Inventory-List-Security-Management-New_2017.csv");
fcsv
.fromStream(stream, { headers: true }) // headers for columns
.on("data", function (data) {
console.log(data);
var woops=data;
MongoClient.connect(url, function(err, db) {
if(err) {
console.log(err);
}
setTimeout(function(){
createNewEntries(db, woops, function(){
if(err)
throw err;
else{
console.log(woops);
}
db.close();
});
},2000);
});
})
.on("end", function () {
console.log("done");
});
}
writeZipCodes();
According to your output,
undefined
[]
ohhhhh
var woops;
var createNewEntries = function(db, woops, callback) {
converter.fromFile("./NTA-SAM-Inventory-List-Security-Management-
New_2017.csv",function(err, result){
// if an error has occured then handle it
if(err){
console.log("An Error Has Occured");
console.log(err);
}
// the result of the conversion
console.log(result); // This is getting printed second
console.log('ohhhhh'); // This is getting printed third
woops=result;
});
console.log(woops); // This is getting printed first
};
MongoClient.connect(url, function(err, db) {
if(err) {
console.log(err);
}
setTimeout(function(){
createNewEntries(db, woops, function(){
if(err)
throw err;
else{
console.log(woops); // This is useless!
}
db.close();
});
},2000);
});
You can clearly see this as woops variable is just declared so it must be having undefined value. And something before ohhhhh must be the result variable.
Now, this definitely means that at least the woops variable is not getting printed after ohhhh or rather, the createNewEntries is getting executed or is returning the result after console.log(woops) is being executed which that means your setTimeout()'s time is not sufficient.
And why are you even using the callback and passing it a function when you're not even using it??? Use this instead-
var woops;
var createNewEntries = function(db, woops) {
converter.fromFile("./NTA-SAM-Inventory-List-Security-Management-
New_2017.csv",function(err, result){
// if an error has occured then handle it
if(err){
console.log("An Error Has Occured");
console.log(err);
}
// the result of the conversion
console.log(result);
console.log('ohhhhh');
woops=result;
}).then(console.log(woops));
};
MongoClient.connect(url, function(err, db) {
if(err) {
console.log(err);
}
createNewEntries(db, woops);
});

Getting error can not get header after they send when read files from directory?

I am trying to get the name and created date of the files. In the code below it throws error when I call the api. It is reading the directory and printing all the file names but it's not sending back to callback. Any idea what is implemented wrong?
service.js
var fs = require('fs');
var path = require('path');
var async = require('async');
var currentDate = new Date();
var objToReturn = [];
var logsDirectory = './logs'
function readDirectory(env, callback) {
fs.readdir(logsDirectory + '/' + env, function(err, files) {
// loop through each file
async.eachSeries(files, function(file, done) {
var dirPath = logsDirectory + '/' + env;
var filePath = path.join(dirPath, file);
var fileInfo = {};
fs.stat(filePath, function(err, stats) {
if (err) {
console.info("File doesn't exist");
} else {
fileInfo.fileDate = stats.birthtime;
fileInfo.filename = file;
objToReturn.push(fileInfo);
done();
}
});
});
},
function(err) {
if (err) {
console.info('error', err);
return;
}
// when you're done reading all the files, do something...
console.log('before Callback', objToReturn);
callback(objToReturn);
});
}
exports.readDirectory = readDirectory;
app.js
var stDirectory = require('./app/serverfiles/stDir');
app.get('/getAllFiles',function(req,res){
var env = req.query.env
console.log('printing',env);
stDirectory.readDirectory(env,function(files){
res.json(files);
console.log('Api files',files);
});
});
There are a few issues:
instead of passing the "final" handler to async.eachSeries(), you're passing it to fs.readdir(), so callback will never get called;
you're declaring objToReturn outside of the function, which isn't a good idea because multiple requests could be handled in parallel;
you're not handling any errors properly;
you should really use the Node.js callback idiom of calling callbacks with two arguments, the first being errors (if there are any) and the second being the result of the asynchronous operation.
The code below should fix these issues:
function readDirectory(env, callback) {
let objToReturn = [];
fs.readdir(
logsDirectory + "/" + env,
function(err, files) {
if (err) return callback(err);
// loop through each file
async.eachSeries(files, function(file, done) {
var dirPath = logsDirectory + "/" + env;
var filePath = path.join(dirPath, file);
var fileInfo = {};
fs.stat(filePath, function(err, stats) {
if (err) {
console.info("File doesn't exist");
return done(err);
} else {
fileInfo.fileDate = stats.birthtime;
fileInfo.filename = file;
objToReturn.push(fileInfo);
done();
}
});
}, function(err) {
if (err) {
console.info("error", err);
return callback(err);
}
// when you're done reading all the files, do something...
console.log("before Callback", objToReturn);
callback(null, objToReturn);
}
);
}
// To call it:
stDirectory.readDirectory(env, function(err, files) {
if (err) {
res.sendStatus(500);
} else {
res.json(files);
console.log('Api files',files);
}
});
You should also consider using async.mapSeries() instead of async.eachSeries() and using a separate array (objToReturn).

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