可读流's的读取方法不返回null

Readable stream's read method does not return null

本文关键字:方法 读取 返回 null      更新时间:2023-09-26

readableStream.read(size)的文档显示,

如果大小字节不可用,那么它将返回null。

为了测试这一点,我做了:

// in test.js
process.stdin.on('readable', function(){
  var d = this.read(30);
  if (d) console.log(d.toString());
});
$ (echo abc; sleep 1; echo def; sleep 1; echo ghi) | node test.js

输出如下:

abc
def
ghi

我期望代码打印null,因为size(30)大于写入的字节数。为什么不打印null

根据@hexacyanide的评论,我将代码改写如下,并再次运行测试:

process.stdin.on('readable', function() {
  var d = this.read(300);
  if (d === null) {
    console.log("NULL")
  } else {
    console.log(d.toString());
  }
});
process.stdin.on('end', function() {
  console.log('END EVENT')
});

测试输出:

NULL
NULL
NULL
abc
def
ghi
END EVENT

我现在可以理解输出,直到3 NULL's
在那之后,我有一些基于输出的问题:

  1. 为什么我第一次测试的输出是abc'ndef'nghi?我之所以这么问,是因为即使将abcdefghi推送到流中,它的缓冲区长度仍然是9。因此,如果我在任何给定时间进行读取,那么读取操作应该返回null。可以肯定的是,我将读取大小设置为300
  2. 流如何知道我已经完成了所有的推送

当试图重现您的问题时,我认为您已经恢复了默认情况下暂停的process.stdin流。后来我发现,当省略这一点时,我得到了你意想不到的输出。这就是NodeJS文档所说的:

stdin流默认情况下是暂停的,因此必须调用process.stdin.resume()从中读取。

在添加readable侦听器之前,我只是在流上使用了resume(),并获得了预期的输出。

我不知道我是否正确,但在您的情况下,我假设每次运行echoreadable都会启动,而在这些情况下read()什么都不读取,但当stdin关闭时,read()只读取所有内容。这是我的测试代码和结果:

process.stdin.on('readable', function() {
  console.log('fire');
  console.log(process.stdin.read(300));
}).on('end', function(){
  console.log("END EVENT")
});

然后我像这样运行代码:(echo abc; sleep 1; echo def; sleep 1; echo ghi) | node test.js,得到了以下结果:

fire
null
fire
null
fire
null
fire
<Buffer 61 62 63 0a 64 65 66 0a 67 68 69 0a>
END EVENT

恢复stdin流后进行测试时,readable触发四次,read(300)正确返回null