2014-07-27 47 views
1

我一直在玩可读和变换流,我无法解决消失线的奥秘。Node.js流和数据消失

考虑一个文本文件中的行包含顺序编号,从1到20000:

$ seq 1 20000 > file.txt 

我创建了一个Readable流和LineStream(从库调用署名npm install byline;我使用4.1.1版本):

var file = (require('fs')).createReadStream('file.txt'); 
var lines = new (require('byline').LineStream)(); 

考虑下面的代码:

setTimeout(function() { 
    lines.on('readable', function() { 
    var line; 
    while (null !== (line = lines.read())) { 
     console.log(line); 
    } 
    }); 
}, 1500); 

setTimeout(function() { 
    file.on('readable', function() { 
    var chunk; 
    while (null !== (chunk = file.read())) { 
     lines.write(chunk); 
    } 
    }); 
}, 1000); 

注意,它首先附加一个监听到'readable'事件file可读流的,其写入到lines流,并且只有一半的第二以后它附加一个监听到'readable'事件lines流的,其简单地打印线路到控制台。

如果我运行此代码,它将只打印16384(即2^14)行并停止。它不会完成文件。但是,如果我将1500毫秒超时更改为500毫秒 - 有效地交换侦听器的连接顺序,它将愉快地打印整个文件。

我试着玩highWaterMark,指定从文件流中读取的字节数量,将监听器附加到行流的其他事件,都是徒劳的。

什么能解释这种行为?

谢谢!

回答

2

我认为这种行为可以用两两件事来说明:

  1. 你如何使用流。
  2. byline如何工作。

你要做的是手动管道。问题在于它不尊重highWaterMark并强制整体被缓冲。

所有这些导致byline表现不佳。看到这个:https://github.com/jahewson/node-byline/blob/master/lib/byline.js#L110-L112。这意味着当缓冲区长度> highWaterMark时,它会停止按下行。但这没有任何意义!它不会阻止内存使用量的增长(行仍然存储在特殊的行缓冲区中),但流不知道这些行,并且如果它以溢出状态结束,它们将永远丢失。

你可以做什么:

  1. 使用pipe
  2. 修改highWaterMarklines._readableState.highWaterMark = Infinity;
  3. 使用byline
+0

感谢停止!这完全解释了它。我已经通过在线的源代码浏览过,但是我相信我缺乏Node的经验。js(尤其是它的流)让我很难看到这个问题。 –