Rajkamal Subramanian
Rajkamal Subramanian

Reputation: 6944

Readable stream's read method does not return null

The doc for readableStream.read(size) says,

if size bytes are not available, then it will return null.

To test this i did:

// 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

The output was the following:

abc
def
ghi

I expected the code to print null, as the size(30) was greater than the bytes written. Why does it not print null?

As per @hexacyanide's comments I rewrote the code as below, and ran the test again:

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')
});

Test output:

NULL
NULL
NULL
abc
def
ghi

END EVENT

I can now understand the output till the 3 NULL's.
After that I have few questions based on the output:

  1. Why did I get abc\ndef\nghi as the output for my first test? I'm asking this because even after pushing abcdefghi to the stream, its buffer length is still 9. So if I read at any give time, the read operation should return null. To be sure, I set the read size to 300.
  2. How does the stream know that I have completed all my pushes?

Upvotes: 2

Views: 1323

Answers (1)

hexacyanide
hexacyanide

Reputation: 91609

When attempting to reproduce your problem, I assumed that you had already resumed the process.stdin stream, which is paused by default. I later found out that when leaving that bit out, I got the unintended output that you were getting. This is what the NodeJS documentation states:

The stdin stream is paused by default, so one must call process.stdin.resume() to read from it.

Before adding the readable listener, I just used resume() on the stream and got the intended output.

I don't know if I'm correct, but in your case, I'd assume that readable is firing each time echo is run, and read() is reading nothing in those cases, but when stdin is closed, read() just reads everything. Here's my test code and results:

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

I then ran that code like so: (echo abc; sleep 1; echo def; sleep 1; echo ghi) | node test.js and got these results:

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

When testing after resuming the stdin stream, readable fires four times, and read(300) properly returns null.

Upvotes: 1

Related Questions