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);
Related
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).
i know this question asked many time before but still i'm struggling to figure this out. i have a set of js files. first one is index.js
app.all('/backend/*/*', function(req, res){ // backend/product/getProduct
serviceType = req.params[0];
methodType = req.params[1];
exports.serviceType= serviceType;
exports.methodType= methodType;
main.checkService()
});
in here im extracting the params and call checkService method in main.js file
main.js
function checkService(){
switch(index.serviceType){
case 'product':
product.checkMethod();
break;
default :
console.log('no such service')
}
}
then it move to product.js file
function checkMethod(){
var methodName = index.methodType,
res = index.res,
req = index.req;
switch(methodName){
case 'samplePost':
var body = req.body;
proHan.samplePost(body,function(data,msg,status){
sendRes(data,msg,status);
});
break;
default :
console.log('no such method')
}
function sendRes(jsonObj,msg,status){
var resObj = {
status : status,
result : jsonObj,
message : msg
}
res.json(resObj);
}
first it moves to samplePost method in handler.js
once the http req finised executing, callback return the results and call sendRes method and send the json
function samplePost(jsonString,cb){
var res = config.setClient('nodeSample');
// jsonString = JSON.parse(jsonString);
res.byKeyField('name').sendPost(jsonString,function(data,msg,status){
cb(data,msg,status);
});
}
to send http req i written a common file. that is config.js
function setClient(_cls){
var client = new Client(url);
return client;
}
function parentClient(url){
this.postBody = {
"Object":{},
"Parameters":{
"KeyProperty":""
}
};
}
function paramChild(){
parentClient.apply( this, arguments );
this.byKeyField = function(_key){
this.postBody.Parameters.KeyProperty = _key;
return this;
}
}
function Client(url){
parentClient.apply( this, arguments );
this.sendPost = function(_body,cb){
_body = (_body) || {};
this.postBody.Object = _body;
var options = {
host : 'www.sample.com',
port : 3300,
path: '/somrthing',
headers: {
'securityToken' : '123'
}
};
options.method = "POST";
var req = http.request(options, function(response){
var str = ''
response.on('data', function (chunk) {
str += chunk;
});
response.on('end', function () {
cb(JSON.parse('[]'),'success',200)
});
});
//This is the data we are posting, it needs to be a string or a buffer
req.on('error', function(response) {
cb(JSON.parse('[]'),response.errno,response.code)
});
req.write(JSON.stringify(this.postBody));
req.end();
}
}
paramChild.prototype = new parentClient();
Client.prototype = new paramChild();
when i send the first req its work but from then again the server crashes. it seems like i can't call res.end method again in a callback method. how can i fix this. thank you.
you can't call res.end two times. Here is a simple exemple to deal with callback with a basic node server.
const http = require('http');
const hostname = '127.0.0.1';
const port = 4242;
let something = true;
function callback(req, res) {
something = !something;
res.setHeader('Content-Type', 'text/plain');
res.end('Callback Hello World\n');
}
const server = http.createServer((req, res) => {
res.statusCode = 200;
if (something) {
callback(req, res);
} else {
something = !something;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World\n');
}
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
Im trying to stub a pouchDB 'put' function but in an invoked function but it is failing.
my DB function-
var PouchDB = require('pouchDB')
var PendingDB = new PouchDB("")
module.exports.addPendingRequest = function(doc, callback){
PendingDB.put(doc, function(err, result){
if(err) {
console.log("Error in PendingDB: addPendingRequest");
console.log(err);
callback(err, null);
}
callback(null, result);
});
console.log("after put: inside addPendingRequest");
}
My Test Function:
var expect = require("chai").expect;
var PendingDB = require("../../lib/administration/PendingDB");
var PouchDB = require('pouchDB');
var sinon = require('sinon');
describe('Testing adding a request', function(){
it('should save the request with email', function(done){
var req = {
_id : "test#email.com",
first_name: "firstTest",
last_name: "test",
id: "test#email.com",
justif: "Testing Purposes",
}
var res = {};
var next = null;
console.log("after req, res, next");
var testOutput = {
success : "success"
};
console.log("after testOutput is set");
var PendingDBTest = sinon.stub(PouchDB.prototype, 'put', function(err, result){
console.log("in stub addReq");
});
console.log("after sinon.stub");
expect(function(){
PendingDB.addPendingRequest(req, function(err, response){
console.log("response");
console.log(response);
});
}).to.not.throw(Error);
expect(PendingDBTest.called).to.equal(true);
PendingDBTest.restore();
done();
})
})
Console:
after req, res, next
after testOutput is set
after sinon.stub
after put: inside addPendingRequest
Therefore PendingDB.put is never entered and my test PendingDBTest.called returns false, thus failing.
Stub on actual object, not on its prototype.
var PendingDBTest = sinon.stub(PouchDB, 'put', function(err, result){
...
Instead of stubbing you could write your tests with the in-memory adapters avaliable for PouchDB:
http://pouchdb.com/adapters.html
In NodeJS:
var PouchDB = require('pouchdb');
var testDB = new PouchDB('testDb', {
db: require('memdown')
});
Or in the Browser:
<script src="pouchdb.js"></script>
<script src="pouchdb.memory.js"></script>
<script>
// this pouch is ephemeral; it only exists in memory
var testDB = new PouchDB('testDB', {
adapter: 'memory'
});
</script>
For example of a project that tests in this way check out: https://github.com/hoodiehq/pouchdb-hoodie-api/tree/master/tests
with the following code I'm able to send an Image to the client with socket.io, but I want also to send the size as a second argument. I would like to understand why the argument "size" is getting always undefined when I try to pass it to the socket.emit function. socket.emit('firstChunkSent', data, size). Can you pls fix it ?
var io = require('../server').io
io.sockets.on('connection', function (socket) {
socket.on('imageRequest', function () {
getTheNewImage(function(data,size){
socket.emit('firstChunkSent', data, size)
});
});
});
function getTheNewImage(callback){
var filename = 'image.gif';
var base64FileSize = fs.stat(filename,function(err,stats){
if (err) { throw err; }
return stats.size
});
var readable = fs.createReadStream(filename, { encoding: 'base64' });
readable.on('readable', function() {
var getImageData = function(){
while (null !== (base64ImageData = readable.read())) {
return base64ImageData
}
}
callback(getImageData(),base64FileSize)
});
readable.on('end', function() {
console.log('there will be no more data.')
});
readable.on('error', function(err) {
console.log('here is the error: '+err)
readable.end(err);
});
return stats.size
Need to use the callback
function getTheNewImage(callback){
var filename = 'image.gif';
var base64FileSize = fs.stat(filename,function(err,stats){
if (err) return callback(new Error(err));
callback(null, stats.size)
});
getTheNewImage(function(data,size)
First param will be the error, not data
I am getting an undefined variable in my code and not sure what the error in my code is:
I get client as undefined when I call getClient...
I have a soap client creation singleton and I have:
var mySingleton = (function() {
var soap = require('soap');
var async = require('async');
var instance;
var client;
function init() {
var url = "http://172.31.19.39/MgmtServer.wsdl";
var endPoint = "https://172.31.19.39:9088";
var options = {};
options.endpoint = endPoint;
async.series([
function(callback) {
soap.createClient(url, options, function (err, result){
console.log('Client is ready');
client = result;
client.setSecurity(new soap.BasicAuthSecurity('admin-priv', 'password'));
callback();
});
}
],
function(err) {
if (err)
return next(err);
});
return {
getClient : function() {
console.log("I will give you the client");
**return client;**
},
publicProperty : "I am also public",
};
};
return {
getInstance : function() {
if (!instance) {
instance = init();
}
return instance;
}
};
})();
module.exports = mySingleton;
so my consumer is :
var soapC = mySingleton.getInstance();
var mySoapClient = soapC.getClient();
I get mySingleton.client is undefined.
Why?
Sure there are better solutions than this one, but it shows you that it can be implemented easier (without async, without singleton):
var soap = require('soap');
var client;
var url = "http://172.31.19.39/MgmtServer.wsdl";
var options = {
endpoint: "https://172.31.19.39:9088"
};
module.exports = {
getClient: function (callback) {
if (client) {
callback(null, client);
return;
}
soap.createClient(url, options, function (err, result) {
if (err) {
callback(err);
return;
}
console.log('Client is ready');
client = result;
client.setSecurity(new soap.BasicAuthSecurity('admin-priv', 'password'));
callback(null, client);
});
},
publicProperty: "I am also public"
};
And when using the client:
// using the client
var mySoapServer = require('./path/to/above/code.js');
mySoapServer.getClient(function (err, client) {
if (err) { /* to error handling and return */ }
client.someRequestMethod(myEnvelope, function (err, response) {
// ...
});
});
There might be a problem when your Soap-Clients gets into trouble (there is no logic to reconnect in case of error). For this you could have a look at the source code of Redis-Client, MySQL-Client, MongoDB-Client, ...
Edit
Some comments on the different aproaches:
The Singleton-pattern is not needed here. Node will execute this JS file only once and further requires get only a reference to the exports. There is no need to create an IIFE scope - the variables won't be visible outside, only the exports.
Programming in Node.js is (besides some special cases) an all-async way. If not done consequently, it just doesn't work or fails/succeeds only if you have good/bad luck.
Error handling looks very much like a lot of boilerplate, but it's necessary in most cases.