Browse Source

stream: simpler stream constructon

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: https://github.com/iojs/io.js/pull/697
Fixes: https://github.com/iojs/readable-stream/issues/102
Reviewed-By: Chris Dickinson <christopher.s.dickinson@gmail.com>
v1.8.0-commit
Sam Newman 10 years ago
committed by Chris Dickinson
parent
commit
50daee7243
  1. 75
      doc/api/stream.markdown
  2. 3
      lib/_stream_readable.js
  3. 8
      lib/_stream_transform.js
  4. 8
      lib/_stream_writable.js
  5. 18
      test/parallel/test-stream-readable-constructor-set-methods.js
  6. 31
      test/parallel/test-stream-transform-constructor-set-methods.js
  7. 34
      test/parallel/test-stream-writable-constructor-set-methods.js

75
doc/api/stream.markdown

@ -718,7 +718,7 @@ of stream class you are writing:
<p>[Writable](#stream_class_stream_writable_1)</p> <p>[Writable](#stream_class_stream_writable_1)</p>
</td> </td>
<td> <td>
<p><code>[_write][]</code></p> <p><code>[_write][]</code>, <code>_writev</code></p>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -729,7 +729,7 @@ of stream class you are writing:
<p>[Duplex](#stream_class_stream_duplex_1)</p> <p>[Duplex](#stream_class_stream_duplex_1)</p>
</td> </td>
<td> <td>
<p><code>[_read][]</code>, <code>[_write][]</code></p> <p><code>[_read][]</code>, <code>[_write][]</code>, <code>_writev</code></p>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -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. 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 ## Streams: Under the Hood
<!--type=misc--> <!--type=misc-->

3
lib/_stream_readable.js

@ -85,6 +85,9 @@ function Readable(options) {
// legacy // legacy
this.readable = true; this.readable = true;
if (options && typeof options.read === 'function')
this._read = options.read;
Stream.call(this); Stream.call(this);
} }

8
lib/_stream_transform.js

@ -105,6 +105,14 @@ function Transform(options) {
// sync guard flag. // sync guard flag.
this._readableState.sync = false; 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() { this.once('prefinish', function() {
if (typeof this._flush === 'function') if (typeof this._flush === 'function')
this._flush(function(er) { this._flush(function(er) {

8
lib/_stream_writable.js

@ -137,6 +137,14 @@ function Writable(options) {
// legacy. // legacy.
this.writable = true; 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); Stream.call(this);
} }

18
test/parallel/test-stream-readable-constructor-set-methods.js

@ -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
test/parallel/test-stream-transform-constructor-set-methods.js

@ -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
test/parallel/test-stream-writable-constructor-set-methods.js

@ -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);
});
Loading…
Cancel
Save