-
Notifications
You must be signed in to change notification settings - Fork 29.7k
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
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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> | ||
|
@@ -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> | ||
|
@@ -1315,6 +1315,135 @@ 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 API Via Revealing Constructor Pattern | ||
|
||
<!--type=misc--> | ||
|
||
To implement any sort of stream you can now pass that streams specific methods as parameters to the constructors options: | ||
|
||
<table> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure this table needs to be duplicated? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, I will remove 😄 |
||
<thead> | ||
<tr> | ||
<th> | ||
<p>Use-case</p> | ||
</th> | ||
<th> | ||
<p>Class</p> | ||
</th> | ||
<th> | ||
<p>Method(s) to implement</p> | ||
</th> | ||
</tr> | ||
</thead> | ||
<tr> | ||
<td> | ||
<p>Reading only</p> | ||
</td> | ||
<td> | ||
<p>[Readable](#stream_class_stream_readable_1)</p> | ||
</td> | ||
<td> | ||
<p><code>[read][_read]</code></p> | ||
</td> | ||
</tr> | ||
<tr> | ||
<td> | ||
<p>Writing only</p> | ||
</td> | ||
<td> | ||
<p>[Writable](#stream_class_stream_writable_1)</p> | ||
</td> | ||
<td> | ||
<p><code>[write][_write]</code></p> | ||
</td> | ||
</tr> | ||
<tr> | ||
<td> | ||
<p>Reading and writing</p> | ||
</td> | ||
<td> | ||
<p>[Duplex](#stream_class_stream_duplex_1)</p> | ||
</td> | ||
<td> | ||
<p><code>[read][_read]</code>, <code>[write][_write]</code>, <code>writev</code></p> | ||
</td> | ||
</tr> | ||
<tr> | ||
<td> | ||
<p>Operate on written data, then read the result</p> | ||
</td> | ||
<td> | ||
<p>[Transform](#stream_class_stream_transform_1)</p> | ||
</td> | ||
<td> | ||
<p><code>transform</code>, <code>flush</code></p> | ||
</td> | ||
</tr> | ||
</table> | ||
|
||
Examples: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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--> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
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); | ||
console.log('ok'); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
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); | ||
console.log('ok'); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
var common = require('../common'); | ||
var assert = require('assert'); | ||
|
||
var Writable = require('stream').Writable; | ||
|
||
(function one() { | ||
var _writeCalled = false; | ||
function _write(d, e, n) { | ||
_writeCalled = true; | ||
} | ||
|
||
var w = new Writable({ write: _write }); | ||
w.end(new Buffer('blerg')); | ||
|
||
process.on('exit', function () { | ||
assert.equal(w._write, _write); | ||
assert(_writeCalled); | ||
console.log('ok 1'); | ||
}); | ||
}()); | ||
|
||
(function two() { | ||
var _writevCalled = false; | ||
var dLength = 0; | ||
|
||
function _writev(d, n) { | ||
dLength = d.length; | ||
_writevCalled = true; | ||
} | ||
|
||
var w = new Writable({ writev: _writev }); | ||
w.cork(); | ||
|
||
w.write(new Buffer('blerg')); | ||
w.write(new Buffer('blerg')); | ||
w.end(); | ||
|
||
process.on('exit', function () { | ||
assert.equal(w._writev, _writev); | ||
assert.equal(dLength, 2); | ||
assert(_writevCalled); | ||
console.log('ok 2'); | ||
}); | ||
}()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Technically I wouldn't call this a revealing constructor pattern, since no functionality is "revealed"; you instead just use
stream.push
andstream.emit("error", ...)
and similar.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get your point, I will amend the description as well.