我正在尝试使用npm包csv-parser来解析我的csv文件,并遇到了发生事件顺序的问题。
按此顺序发出事件
显然节点的异步性质意味着我在第一个'data'事件发出时没有返回'headers'中的慢速数据库访问,因此我还没有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);
})
答案 0 :(得分:1)
当您收到headers
事件时,unpipe()
读取流。这将使文件阅读器处于暂停状态,因此您不必在内存中缓冲大量内容。
由于数据是以块的形式从磁盘读取的(通常为64 kB),因此CSV解析器在继续解析当前块时仍会发出data
个事件。您仍然需要缓冲数组中的少量行。
当您从数据库获得所需的所有信息时:
将缓冲的行提交到数据库。
删除原始data
事件处理程序(排队到数组的处理程序)并附加一个直接将数据提交到数据库的处理程序。
pipe()
读取流回CSV解析器。
您可能还想考虑如果您的程序从磁盘读取并以比数据库接受数据更快的速度解析CSV会发生什么。由于没有背压,大量的数据库操作最终可能会在内存中排队,直到用完为止。
如果有许多待处理的数据库操作,则应暂停文件读取流。