Reputation: 2757
So in my setup I have about 7 different ftp servers running on my network, and I want to be able to create multiple ftp clients in my node app to fetch some files from these servers respectively. I was wondering if that is even possible or not? I am looking at using the ftp npm package: https://www.npmjs.com/package/ftp
I have tried a couple things like the following where I create multiple instances of the client in an array and then spawn them off by doing a connect at the end of the iteration.
// Create all the clients for each host
// Note that config here is just a JSON object I read at the start
numAddresses = Object.keys(config.addresses).length; //7
clients=[];
for (address in config.addresses) {
// current address being processed
console.log(config.addresses[address]);
// create a new client for this address
clients[address] = createClient(path);
// update the settings for this new client based on address
// note we keep the default anonymous login credential
// you can change it here though
connectionSettings.host = config.addresses[address].ip;
connectionSettings.port = config.addresses[address].port;
console.log(connectionSettings);
// connect the current client with the associated settings
clients[address].connect(connectionSettings);
}
// creates a ftp client and returns it
function createClient(path) {
var client = new Client();
// define wait for the server handshake (greeting)
client.on('greeting', afterGreeting);
return client;
}
// handles the flow after server handshake (greeting)
function afterGreeting(msg, client) {
console.log(msg);
// define wait for the server 'ready' state
client.on('ready', afterReady);
}
// handles the flow after server 'ready' state
function afterReady() {
console.log('ready');
performListing(path);
}
// handles the listing of the files
function performListing(path) {
console.log('fetching from:'+path);
client.list(path, performFetch);
}
// handles the fetching of the files
function performFetch(err, list){
if (err) throw err;
list.forEach(function (element, index, array) {
console.log('now copying: '+element.name);
});
client.end();
}
I expected this to just spawn off all the instances of those clients in the loop but I get this error:
D:\node_workspace\ftp\main.js:52
client.on('ready', afterReady);
TypeError: Cannot read property 'on' of undefined
I think I am running into some very basic error with my assumptions of how node works (I am a beginner). Any help would be appreciated.
Upvotes: 0
Views: 584
Reputation: 667
Try the following code...
var Client = require("ftp");
numAddresses = Object.keys(config.addresses).length;
clients = [];
for (address in config.addresses) {
// current address being processed
console.log(config.addresses[address]);
// create a new client for this address
clients[address] = createClient(path);
// update the settings for this new client based on address
// note we keep the default anonymous login credential
// you can change it here though
connectionSettings.host = config.addresses[address].ip;
connectionSettings.port = config.addresses[address].port;
console.log(connectionSettings);
// connect the current client with the associated settings
clients[address].connect(connectionSettings);
}
function createClient(path) {
var c = new Client();
c.on('greeting', (msg) => {
afterGreeting(msg, c);
});
return c;
}
function afterGreeting(msg, client) {
console.log(msg);
client.on('ready', () => {
afterReady(client);
});
}
function afterReady(client) {
console.log('ready');
performListing(path, client);
}
function performListing(path, client) {
console.log('fetching from:' + path);
client.list(path, (err, list) => {
performFetch(err, list, client);
});
}
function performFetch(err, list, client) {
if (err) throw err;
list.forEach(function (element, index, array) {
console.log('now copying: ' + element.name);
});
client.end();
}
Updated
var Client = require("ftp");
numAddresses = Object.keys(config.addresses).length;
clients = [];
for (address in config.addresses) {
// current address being processed
console.log(config.addresses[address]);
// create a new client for this address
clients[address] = createClient(path);
// update the settings for this new client based on address
// note we keep the default anonymous login credential
// you can change it here though
connectionSettings.host = config.addresses[address].ip;
connectionSettings.port = config.addresses[address].port;
console.log(connectionSettings);
// connect the current client with the associated settings
clients[address].connect(connectionSettings);
}
function createClient(path) {
// initialize new client
var c = new Client();
// official npm documentation https://www.npmjs.com/package/ftp#events
// tells us, that greeting returns a string so we need to pass a callback
// to c.on('greeting', callback)
// we could either write function(msg) { } or short form (msg) => { }
c.on('greeting', (msg) => {
afterGreeting(msg, c);
});
return c;
}
function afterGreeting(msg, client) {
console.log(msg);
// ready needs a callback too but returns nothing, only calls this callback
// if ready is ready. Kappa.
client.on('ready', () => {
afterReady(client);
});
}
function afterReady(client) {
console.log('ready');
performListing(path, client);
}
function performListing(path, client) {
console.log('fetching from:' + path);
// client.list returns an err if we encounter an error and a list
// our callback is written in shortform (err, list) => { } so we're
// passing those callback data to this anonymous function
client.list(path, (err, list) => {
performFetch(err, list, client);
});
}
function performFetch(err, list, client) {
if (err) throw err;
list.forEach(function (element, index, array) {
console.log('now copying: ' + element.name);
});
client.end();
}
Answer to question: Depends on your program. You always can rewrite and optimize a program.
Upvotes: 1