javascript - 使用 csv-parser 同步发出事件

标签 javascript node.js node.js-stream

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

事件按此顺序发出

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

显然, Node 的异步性质意味着在发出第一个“数据”事件时,我在“ header ”中缓慢的数据库访问尚未返回,因此我还没有 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);
    })

最佳答案

  1. 当您收到 headers 事件时,unpipe()读取流。这将使文件读取器进入暂停状态,这样您就不必在内存中缓冲一堆内容。

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

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

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

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

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

<小时/>

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

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

关于javascript - 使用 csv-parser 同步发出事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45111875/

相关文章:

javascript - 交换javascript数组中的两个项目

node.js - 如何以及何时生成 Node/Express cookie secret ?

Node.js stream into zip archive 和 stream zip archive 作为对客户端的响应

node.js - 如何将图像写入具有缓冲区的服务器?

javascript - 使用另一个对象的属性作为键查找对象

javascript - Kendo UI Splitview 刷新 Pane 内容

javascript - 从 URL 返回 innerHTML

javascript - 将 php 变量保存到函数中的脚本变量

javascript - Cypress 使用请求正文中的文件进行 HTTP POST 时出错