Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a Node.js Readable stream from a JavaScript object — The simplest possible way

Can anyone explain why I'm getting an error after running the following code with node v0.10.21?

I'm aware that I could JSON.stringify() that object in order to achieve more or less the same result, the point here is to make sense of stream.Readable when objectMode is set true.

The error:

net.js:612
    throw new TypeError('invalid data');
          ^
TypeError: invalid data
    at WriteStream.Socket.write (net.js:612:11)
    at write (_stream_readable.js:583:24)
    at flow (_stream_readable.js:592:7)
    at _stream_readable.js:560:7
    at process._tickCallback (node.js:415:13)
    at Function.Module.runMain (module.js:499:11)
    at startup (node.js:119:16)
    at node.js:901:3

The code:

var stream = require('stream');
var edad = require(__dirname + '/public/edad.json');

var rs = new stream.Readable({ objectMode: true });

rs.push(edad);
rs.push(null);
rs.pipe(process.stdout);
like image 236
n370 Avatar asked Jan 14 '14 21:01

n370


People also ask

How do I create a readable stream in node?

To implement a readable stream, we require the Readable interface, and construct an object from it, and implement a read() method in the stream's configuration parameter: const { Readable } = require('stream'); const inStream = new Readable({ read() {} }); There is a simple way to implement readable streams.

Which object is a stream in node JS?

Streams are objects that allows developers to read/write data to and from a source in a continuous manner. There are four main types of streams in Node. js; readable, writable, duplex and transform.

Which of the following methods is used to switch between modes in readable stream mode?

One of the ways of switching the mode of a stream to flowing is to attach a 'data' event listener. A way to switch the readable stream to a flowing mode manually is to call the stream. resume method.


3 Answers

rs is an objectMode stream, but process.stdout is not, so it is expecting to have Buffer instances written into it. Since it is getting the wrong data type, it is throwing an error.

If you wanted to be able to pipe the objects like this, you would need to have an in-between stream that supports writing as objects and reading as Buffers.

Something like this:

var stream = require('stream');
var util = require('util');

function StringifyStream(){
    stream.Transform.call(this);

    this._readableState.objectMode = false;
    this._writableState.objectMode = true;
}
util.inherits(StringifyStream, stream.Transform);

StringifyStream.prototype._transform = function(obj, encoding, cb){
    this.push(JSON.stringify(obj));
    cb();
};


var edad = require(__dirname + '/public/edad.json');

var rs = new stream.Readable({ objectMode: true });
rs.push(edad);
rs.push(null);

rs.pipe(new StringifyStream()).pipe(process.stdout);
like image 67
loganfsmyth Avatar answered Oct 22 '22 03:10

loganfsmyth


As loganfsmyth noted, rs is in objectMode, while process.stdout isn't. So it is expecting to have Buffers/Strings written to it, and is throwing a TypeError when it gets an Object.

We need to convert the stream of Objects into text, which is what JSONStream is made to do:

JSONStream = require('JSONStream');
rs.pipe(JSONStream.stringify()).pipe(process.stdout);
like image 4
slang Avatar answered Oct 22 '22 04:10

slang


I am a person who does not know much about Node (I just need to have my Gulp setup working). Because of that, the fact that I need 20+ lines of code and weird calls like stream.push(null) to work with variable in the stream seems a little crazy.

This worked for me:

var data = { "prop1": "val1", "prop2": "val2" };
var dest = 'path/to/dest/config.json';
var s = require('stream');

var stream = new s.Readable();
stream.push(JSON.stringify(data));    // stream apparently does not accept objects
stream.push(null);                    // no idea why this is needed, but it is

return stream
    .pipe()                           // whatever you need
    .pipe($.fs.createWriteStream(dest));
like image 2
Petr Cibulka Avatar answered Oct 22 '22 05:10

Petr Cibulka