节点流逐行关闭事件

时间:2017-05-15 13:08:47

标签: javascript node.js readline

我从http帖子收到一个大文件。我需要从该文件中取出每一行并将其插入数据库。通过一次插入500行左右来实现这一点要快得多,所以这就是我所拥有的:

var readline = require('readline');

var insertSize = 500;
var records = [];

var reader = readline.createInterface({
  input: inputStream
});
reader.on('line', function(line) {
  reader.pause();
  var entry = line.split('\t');
  if (entry.length != 3) return reader.resume();

  records.push({
    first: entry[0],
    second: entry[1],
    third: entry[2]
  });

  if (records.length < insertSize) return reader.resume();

  database.create(records).exec(function (err) {
    if (err) return res.serverError(err);
    records.length = 0;
    reader.resume();
  });
});
reader.on('error', function(err) {
  return res.serverError(err);
});
reader.on('close', function() {
  database.create(records).exec(function (err) {
    if (err) return res.serverError(err);
    return res.ok();
  });
});

根据文档,line之后仍可触发closepause()事件。我发现这种情况发生了,因为在close事件中database.create()完成之前触发了line事件。有没有更好的方法来处理这个? line-by-line会很好,但它不能将流作为输入。感谢。

1 个答案:

答案 0 :(得分:0)

使用split我能够避免这个问题。暂停流时不会触发end事件。

var split = require('split');

var insertSize = 500;
var records = [];

readStream.pipe(split())
.on('error', function (err) {
  return res.serverError(err);
})
.on('data', function (line) {
  var _this = this;
  this.pause();
  var entry = line.split('\t');
  if (entry.length != 3) return this.resume();
  records.push({
    first: entry[0],
    second: entry[1],
    third: entry[2]
  });

  if (records.length < insertSize) return this.resume();

  database.create(records).exec(function (err) {
    if (err) return res.serverError(err);
    records.length = 0;
    _this.resume();
  });
})
.on('end', function () {
  database.create(records).exec(function (err) {
    if (err) return callback(err);
    return res.ok();
  });
});