Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stream: simpler stream constructon #697

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 73 additions & 2 deletions doc/api/stream.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -718,7 +718,7 @@ of stream class you are writing:
<p>[Writable](#stream_class_stream_writable_1)</p>
</td>
<td>
<p><code>[_write][]</code></p>
<p><code>[_write][]</code>, <code>_writev</code></p>
</td>
</tr>
<tr>
Expand All @@ -729,7 +729,7 @@ of stream class you are writing:
<p>[Duplex](#stream_class_stream_duplex_1)</p>
</td>
<td>
<p><code>[_read][]</code>, <code>[_write][]</code></p>
<p><code>[_read][]</code>, <code>[_write][]</code>, <code>_writev</code></p>
</td>
</tr>
<tr>
Expand Down Expand Up @@ -1315,6 +1315,77 @@ for examples and testing, but there are occasionally use cases where
it can come in handy as a building block for novel sorts of streams.


## Simplified Constructor API

<!--type=misc-->

In simple cases there is now the added benefit of being able to construct a stream without inheritance.

This can be done by passing the appropriate methods as constructor options:

Examples:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are lovely illustrations of how you no longer need to subclass for simple cases. I might even call that out as an explicit benefit.


### Readable
```javascript
var readable = new stream.Readable({
read: function(n) {
// sets this._read under the hood
}
});
```

### Writable
```javascript
var writable = new stream.Writable({
write: function(chunk, encoding, next) {
// sets this._write under the hood
}
});

// or

var writable = new stream.Writable({
writev: function(chunks, next) {
// sets this._writev under the hood
}
});
```

### Duplex
```javascript
var duplex = new stream.Duplex({
read: function(n) {
// sets this._read under the hood
},
write: function(chunk, encoding, next) {
// sets this._write under the hood
}
});

// or

var duplex = new stream.Duplex({
read: function(n) {
// sets this._read under the hood
},
writev: function(chunks, next) {
// sets this._writev under the hood
}
});
```

### Transform
```javascript
var transform = new stream.Transform({
transform: function(chunk, encoding, next) {
// sets this._transform under the hood
},
flush: function(done) {
// sets this._flush under the hood
}
});
```

## Streams: Under the Hood

<!--type=misc-->
Expand Down
3 changes: 3 additions & 0 deletions lib/_stream_readable.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ function Readable(options) {
// legacy
this.readable = true;

if (options && typeof options.read === 'function')
this._read = options.read;

Stream.call(this);
}

Expand Down
8 changes: 8 additions & 0 deletions lib/_stream_transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,14 @@ function Transform(options) {
// sync guard flag.
this._readableState.sync = false;

if (options) {
if (typeof options.transform === 'function')
this._transform = options.transform;

if (typeof options.flush === 'function')
this._flush = options.flush;
}

this.once('prefinish', function() {
if (typeof this._flush === 'function')
this._flush(function(er) {
Expand Down
8 changes: 8 additions & 0 deletions lib/_stream_writable.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,14 @@ function Writable(options) {
// legacy.
this.writable = true;

if (options) {
if (typeof options.write === 'function')
this._write = options.write;

if (typeof options.writev === 'function')
this._writev = options.writev;
}

Stream.call(this);
}

Expand Down
18 changes: 18 additions & 0 deletions test/parallel/test-stream-readable-constructor-set-methods.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
var common = require('../common');
var assert = require('assert');

var Readable = require('stream').Readable;

var _readCalled = false;
function _read(n) {
_readCalled = true;
this.push(null);
}

var r = new Readable({ read: _read });
r.resume();

process.on('exit', function () {
assert.equal(r._read, _read);
assert(_readCalled);
});
31 changes: 31 additions & 0 deletions test/parallel/test-stream-transform-constructor-set-methods.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
var common = require('../common');
var assert = require('assert');

var Transform = require('stream').Transform;

var _transformCalled = false;
function _transform(d, e, n) {
_transformCalled = true;
n();
}

var _flushCalled = false;
function _flush(n) {
_flushCalled = true;
n();
}

var t = new Transform({
transform: _transform,
flush: _flush
});

t.end(new Buffer('blerg'));
t.resume();

process.on('exit', function () {
assert.equal(t._transform, _transform);
assert.equal(t._flush, _flush);
assert(_transformCalled);
assert(_flushCalled);
});
34 changes: 34 additions & 0 deletions test/parallel/test-stream-writable-constructor-set-methods.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
var common = require('../common');
var assert = require('assert');

var Writable = require('stream').Writable;

var _writeCalled = false;
function _write(d, e, n) {
_writeCalled = true;
}

var w = new Writable({ write: _write });
w.end(new Buffer('blerg'));

var _writevCalled = false;
var dLength = 0;
function _writev(d, n) {
dLength = d.length;
_writevCalled = true;
}

var w2 = new Writable({ writev: _writev });
w2.cork();

w2.write(new Buffer('blerg'));
w2.write(new Buffer('blerg'));
w2.end();

process.on('exit', function () {
assert.equal(w._write, _write);
assert(_writeCalled);
assert.equal(w._writev, _writev);
assert.equal(dLength, 2);
assert(_writevCalled);
});