Skip to content

Commit

Permalink
stream: simpler stream constructon
Browse files Browse the repository at this point in the history
Adds simplified constructor pattern, allowing users
to provide "read", "write", "transform", "flush", and
"writev" functions as stream options in lieu of subclassing.

Semver: minor
PR-URL: #697
Fixes: nodejs/readable-stream#102
Reviewed-By: Chris Dickinson <[email protected]>
  • Loading branch information
sonewman authored and chrisdickinson committed Feb 5, 2015
1 parent e0730ee commit 50daee7
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 2 deletions.
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:

### 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(w2._writev, _writev);
assert.equal(dLength, 2);
assert(_writevCalled);
});

0 comments on commit 50daee7

Please sign in to comment.