【问题标题】:Synchronous Emitted Events With csv-parser使用 csv-parser 同步发出的事件
【发布时间】:2017-12-20 01:56:10
【问题描述】:

我正在尝试使用 npm 包 csv-parser 来解析我的 csv 文件,但遇到了事件发生顺序的问题。

事件按此顺序发出

  1. 'headers':想要将有关 csv 的元数据插入数据库并返回一个 id 值
  2. 'data':想要将headers事件返回的id值用于所有数据事件
  3. '数据'
  4. '数据'
  5. ...
  6. 结束

显然节点的异步性质意味着我在“标题”中的缓慢数据库访问在第一个“数据”事件发出时尚未返回,因此我还没有 csv 的 ID。我能想到的唯一选择是将所有数据行缓存到某个临时变量中,然后在读取整个 csv 后推送所有内容。考虑到我可能有非常大的 csv 文件,这似乎是个坏主意?对解决此问题的更好方法有何建议?

编辑:添加了一些代码(伪代码,未经实际测试)

let headerList = null;
let dataArray = [];
fs.createReadStream(path)
    .pipe(csv())
    // Parse the headers into a comma delimminated string
    .on('headers', function(headers) {
        // some parsing logic and then assigned to variable
        headerList = headers;
    })
    .on('data', function (data) {
        // Some push of data into a variable
        dataArray.push(data);
    })
    .on('end', function() {
        // create the base upload object
        const id = uploads.createUpload(filename, headerList, new Date());

        // insert data
        uploads.insertUploadData(id, dataArray);
    })

【问题讨论】:

  • 也许读第一行,只是为了获取元数据。进行数据库调用。当第一个数据库调用返回 id 时,然后执行完整的解析过程......然后你不必缓存任何东西。只需将第一行读两遍。
  • 是的,这不是一个坏主意。没想到那样做。

标签: javascript node.js node.js-stream


【解决方案1】:
  1. 当您收到headers 事件时,unpipe() 读取流。这将使文件阅读器进入暂停状态,因此您不必在内存中缓冲一堆东西。

  2. 由于数据是以块(通常为 64 kB)从磁盘读取的,因此 CSV 解析器在继续解析当前块时仍会发出 data 事件。您仍然需要缓冲数组中的少量行。

  3. 当您从数据库中获得所需的所有信息时:

    1. 将缓冲的行提交到数据库。

    2. 删除原来的 data 事件处理程序(排队到数组中的事件处理程序)并附加一个直接向数据库提交行的事件处理程序。

    3. pipe() 将读取流返回给 CSV 解析器。


您可能还想考虑如果您的程序从磁盘读取并解析 CSV 的速度快于您的数据库接受数据的速度会发生什么。由于没有背压,大量数据库操作最终可能会在内存中排队,直到用完为止。

如果有许多待处理的数据库操作,您应该暂停文件读取流。

【讨论】:

  • 有道理。没有意识到你可以像这样解开流。谢谢
  • 是的,关于积压的问题很好。考虑到它将在不同的服务器上,我想这种情况很有可能。
猜你喜欢
  • 2015-08-26
  • 1970-01-01
  • 1970-01-01
  • 2021-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-25
  • 1970-01-01
相关资源
最近更新 更多