2016-06-22 2 views
2

Я знаю, что это какая-то асинхронная головоломка, в которую я попал, но я пытаюсь загрузить несколько файлов внутри обратного вызова из метода .list любого из разных FTP-пакетов npm.Узел FTP: множественные асинхронные вызовы внутри цикла

Так что-то вроде этого (примечание: JSFTP здесь просто оберткой node-ftp, я получаю один и тот же вопрос с этим один):

ftp = new JSFTP(conf.FTPConfig) 
    ftp.ls(conf.remoteFolder, (err, fileList) => { 
    if (err) return console.error(err) 

    for (let i=0; i<fileList.length; i++){ 
     file = fileList[i] 
     ftp.get(file.name, `./Downloaded/${file.name}`, err => { 
     if (err) return console.error(err) 
     console.log(`${file.name} copied.`) 
     }) 
    } 
    }) 

Если я не использую петлю и загрузить только один файл , все работает нормально. Но с петлей, я получаю следующие ошибки, и я не получаю какой-либо из файлов (за исключением одного или двух пустых заполнителей файлов):

(Короче): Error: 503 Bad sequence of commands, и далее: 'Probably trying a PASV operation while one is in progress

Похоже, что он запускает все мои вызовы .get внутри цикла (очевидно, не дожидаясь окончания какого-либо из них, что хорошо), но затем не удается выполнить все вызовы .get таким образом? Должны ли они не просто запускаться параллельно, асинхронно?

{ Error: 503 Bad sequence of commands. 
    at Ftp.parse (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:257:11) 
    at Ftp.parseResponse (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:174:8) 
    at Stream.<anonymous> (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:146:24) 
    at emitOne (events.js:96:13) 
    at Stream.emit (events.js:188:7) 
    at ResponseParser.reemit (C:\Git\SenecaFTP\FTPMonitor\node_modules\duplexer\index.js:70:25) 
    at emitOne (events.js:96:13) 
    at ResponseParser.emit (events.js:188:7) 
    at readableAddChunk (_stream_readable.js:172:18) 
    at ResponseParser.Readable.push (_stream_readable.js:130:10) code: 503 } 
{ Error: 503 Bad sequence of commands. 
    at Ftp.parse (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:257:11) 
    at Ftp.parseResponse (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:174:8) 
    at Stream.<anonymous> (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:146:24) 
    at emitOne (events.js:96:13) 
    at Stream.emit (events.js:188:7) 
    at ResponseParser.reemit (C:\Git\SenecaFTP\FTPMonitor\node_modules\duplexer\index.js:70:25) 
    at emitOne (events.js:96:13) 
    at ResponseParser.emit (events.js:188:7) 
    at readableAddChunk (_stream_readable.js:172:18) 
    at ResponseParser.Readable.push (_stream_readable.js:130:10) code: 503 } 
{ Error: 503 Bad sequence of commands. 
    at Ftp.parse (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:257:11) 
    at Ftp.parseResponse (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:174:8) 
    at Stream.<anonymous> (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:146:24) 
    at emitOne (events.js:96:13) 
    at Stream.emit (events.js:188:7) 
    at ResponseParser.reemit (C:\Git\SenecaFTP\FTPMonitor\node_modules\duplexer\index.js:70:25) 
    at emitOne (events.js:96:13) 
    at ResponseParser.emit (events.js:188:7) 
    at readableAddChunk (_stream_readable.js:172:18) 
    at ResponseParser.Readable.push (_stream_readable.js:130:10) code: 503 } 
{ Error: 503 Bad sequence of commands. 
    at Ftp.parse (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:257:11) 
    at Ftp.parseResponse (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:174:8) 
    at Stream.<anonymous> (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:146:24) 
    at emitOne (events.js:96:13) 
    at Stream.emit (events.js:188:7) 
    at ResponseParser.reemit (C:\Git\SenecaFTP\FTPMonitor\node_modules\duplexer\index.js:70:25) 
    at emitOne (events.js:96:13) 
    at ResponseParser.emit (events.js:188:7) 
    at readableAddChunk (_stream_readable.js:172:18) 
    at ResponseParser.Readable.push (_stream_readable.js:130:10) code: 503 } 
{ Error: 503 Bad sequence of commands. 
    at Ftp.parse (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:257:11) 
    at Ftp.parseResponse (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:174:8) 
    at Stream.<anonymous> (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:146:24) 
    at emitOne (events.js:96:13) 
    at Stream.emit (events.js:188:7) 
    at ResponseParser.reemit (C:\Git\SenecaFTP\FTPMonitor\node_modules\duplexer\index.js:70:25) 
    at emitOne (events.js:96:13) 
    at ResponseParser.emit (events.js:188:7) 
    at readableAddChunk (_stream_readable.js:172:18) 
    at ResponseParser.Readable.push (_stream_readable.js:130:10) code: 503 } 
{ Error: 503 Bad sequence of commands. 
    at Ftp.parse (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:257:11) 
    at Ftp.parseResponse (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:174:8) 
    at Stream.<anonymous> (C:\Git\SenecaFTP\FTPMonitor\node_modules\jsftp\lib\jsftp.js:146:24) 
    at emitOne (events.js:96:13) 
    at Stream.emit (events.js:188:7) 
    at ResponseParser.reemit (C:\Git\SenecaFTP\FTPMonitor\node_modules\duplexer\index.js:70:25) 
    at emitOne (events.js:96:13) 
    at ResponseParser.emit (events.js:188:7) 
    at readableAddChunk (_stream_readable.js:172:18) 
    at ResponseParser.Readable.push (_stream_readable.js:130:10) code: 503 } 
{ Error: connect ECONNREFUSED 192.168.100.161:61229 
    at Object.exports._errnoException (util.js:1007:11) 
    at exports._exceptionWithHostPort (util.js:1030:20) 
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1080:14) 
    code: 'ECONNREFUSED', 
    errno: 'ECONNREFUSED', 
    syscall: 'connect', 
    address: '192.168.100.161', 
    port: 61229, 
    msg: 'Probably trying a PASV operation while one is in progress' } 

ответ

3

После просмотра у источника для jsftp оказывается, что это создает одно соединение и использует только один сокет: https://github.com/sergi/jsftp/blob/master/lib/jsftp.js#L120

Это означает, что она не создает новое соединение для каждой команды, но использует одно соединение для отправки команд через. В принципе, вы можете обойти это, создав новый экземпляр SFTP для каждого файла, который вы хотите загрузить.

В основном переделки код для этого:

ftp = new JSFTP(conf.FTPConfig) 
 
    ftp.ls(conf.remoteFolder, (err, fileList) => { 
 
    if (err) return console.error(err) 
 

 
    for (let i=0; i<fileList.length; i++){ 
 
     file = fileList[i] 
 
     new JSFTP(conf.FTPConfig).get(file.name, `./Downloaded/${file.name}`, err => { 
 
     if (err) return console.error(err) 
 
     console.log(`${file.name} copied.`) 
 
     }) 
 
    } 
 
    })

Однако я бы рекомендовал использовать какой-то библиотеки, такие как async управления потоком или с использованием раствора на основе обещания, как это могло бы быть немного более управляемым.

Существует также аналогичный вопрос о SO с аналогичным решением с использованием модуля async я упоминал: Downloading multiple file from ftp site using node js

+0

Да это помогло много, большое спасибо! Я закончил тем, что вы указали простой маршрут. Вероятно, я должен попробовать библиотеку Async в будущем. Но сейчас это было просто необходимо для доказательства концепции. Еще раз спасибо! – batjko

Смежные вопросы