暂停Node.js中的readline

Mic*_*itt 11 node.js

考虑下面的代码......我试图在阅读前5行后暂停流:

var fs          = require('fs');
var readline    = require('readline');
var stream      = require('stream');
var numlines    = 0;
var instream    = fs.createReadStream("myfile.json");
var outstream   = new stream;
var readStream = readline.createInterface(instream, outstream);
readStream.on('line', function(line){
  numlines++;
  console.log("Read " + numlines + " lines");
  if (numlines >= 5) {
    console.log("Pausing stream");
    readStream.pause();
  }
});
Run Code Online (Sandbox Code Playgroud)

输出(下一个复制)表明它在暂停后继续读取行.也许readline已经在缓冲区排队了几行,无论如何都要把它们送给我......如果它继续在后台异步读取会有意义,但根据文档,我不知道是什么应该是正确的行为.有关如何达到预期效果的任何建议?

Read 1 lines
Read 2 lines
Read 3 lines
Read 4 lines
Read 5 lines
Pausing stream
Read 6 lines
Pausing stream
Read 7 lines
Run Code Online (Sandbox Code Playgroud)

Ale*_*ara 16

有点不直观,暂停方法不会停止排队的事件:

调用rl.pause()不会立即暂停实例'line'发出的其他事件(包括)readline.Interface.

然而,有一个名为第三方模块line-by-line,其中pause 确实暂停line事件,直到它被恢复.

var LineByLineReader = require('line-by-line'),
    lr = new LineByLineReader('big_file.txt');

lr.on('error', function (err) {
  // 'err' contains error object
});

lr.on('line', function (line) {
  // pause emitting of lines...
  lr.pause();

  // ...do your asynchronous line processing..
  setTimeout(function () {

      // ...and continue emitting lines.
      lr.resume();
  }, 100);
});

lr.on('end', function () {
  // All lines are read, file is closed now.
});
Run Code Online (Sandbox Code Playgroud)

(我与该模块没有任何关系,只是发现它对处理这个问题很有帮助.)

  • @ZachSmith 我发现当回调不能或不应该同步完成(例如,将行插入数据库)时,能够随意暂停和恢复非常有用。如果您读取行的速度比处理它们的速度快,则可能会排队过多的请求并耗尽内存。 (2认同)

Mic*_*itt 9

因此,事实证明,即使在暂停()之后,readline流也倾向于"滴"(即,泄漏一些额外的行).文档没有说清楚,但这是真的.

如果希望pause()切换立即出现,则必须创建自己的行缓冲区并自行累积剩余行.