我需要从Node.JS解析CSV文档,为每条记录(=每行)执行数据库操作。但是,我无法使用pull方法找到合适的CSV解析器,或者至少在解析下一行之前等待我的记录操作的推送方法。
我查看了csv-parse
,csvtojson
,csv-streamify
,但他们似乎都在连续流中推送事件而没有任何流量控制。如果解析1000行CSV文档,我基本上可以快速顺序获得所有1000个回调。对于每条记录,我执行一个返回承诺的操作。目前我不得不求助于将所有承诺推送到一个数组中,在获得done/end
事件后,我也等待Promise.all(myOperations)
知道文档何时完全处理。但这不是很好,而且,我更喜欢一次解析一行并完全处理它,然后获取下一条记录,而不是同时处理所有记录 - 它很难调试并使用大量内存而不是简单地按顺序处理每个记录。
那么,是否有一个支持拉模式的CSV解析器,或者是一种获取任何基于流的CSV解析器(最好是csvtojson
的方式,因为我正在使用的那个)仅生成事件的方法我的前一个记录的处理程序完成后的新记录(使用promises)?
答案 0 :(得分:0)
如果要异步处理每一行,可以使用节点的本地LineReader来执行此操作。
const lineStream = readline.createInterface({
input: fs.createReadStream('data/test.csv'),
});
lineStream.on('line', (eachLine) =>{
//process each line
});
如果您想以同步方式执行相同操作,可以使用line-by-line。它不会将整个文件缓冲到内存中。它提供事件处理程序来暂停和恢复“'发出事件。
lr.on('line', function (line) {
// pause emitting of lines...
lr.pause();
// ...do your asynchronous line processing..
setTimeout(function () {
// ...and continue emitting lines. (1 sec delay)
lr.resume();
}, 1000);
});
答案 1 :(得分:0)
我自己通过创建自己的Writable
来解决这个问题并将CSV解析器传递给它。我的write方法做了它的东西并包装传递给_write()的节点回调的承诺(这里使用Q.nodeify实现):
class CsvConsumer extends stream.Writable {
_write(data, encoding, cb) {
console.log('Got data: ', data);
Q.delay(1000).then(() => {
console.log('Waited 1 s');
}).nodeify(cb);
}
}
csvtojson()
.fromStream(is)
.pipe(new CsvConsumer())
.on('finish', err => {
if (err) {
console.log('Error!');
} else {
console.log('Done!');
}
});
这将逐个处理行:
Got data: {"a": "1"}
Waited 1 s
Got data: {"a": "2"}
Waited 1 s
Got data: {"a": "3"}
Waited 1 s
Done!