【问题标题】:Node FTP: Multiple asynchronous calls inside loop节点 FTP:循环内的多个异步调用
【发布时间】:2016-06-22 19:46:36
【问题描述】:

我知道这是我自己遇到的一些异步难题,但我正在尝试在 npm 的各种 FTP 包的 .list 方法的回调中下载多个文件。

所以是这样的(注意:这里的 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' }

【问题讨论】:

    标签: node.js asynchronous ftp node-ftp


    【解决方案1】:

    查看 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 或使用基于 Promise 的解决方案,因为它可能更易于管理。

    关于 SO 也有一个类似的问题,使用我提到的async 模块的类似解决方案:Downloading multiple file from ftp site using node js

    【讨论】:

    • 是的,这很有帮助,非常感谢!我最终选择了你上面提到的简单路线。我将来可能应该尝试 Async 库。但现在,这只是概念证明所需要的。再次感谢!
    猜你喜欢
    • 2014-11-05
    • 2018-07-09
    • 2021-09-11
    • 1970-01-01
    • 1970-01-01
    • 2018-10-17
    • 1970-01-01
    • 2012-09-10
    • 2019-03-24
    相关资源
    最近更新 更多