stream: construct

Provide a standardized way of asynchronously creating and
initializing resources before performing any work.

Refs: https://github.com/nodejs/node/issues/29314

PR-URL: https://github.com/nodejs/node/pull/29656
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
This commit is contained in:
Robert Nagy 2019-08-25 18:13:27 +02:00
parent 9949a2e1e3
commit fb8cc72e73
5 changed files with 544 additions and 20 deletions

View file

@ -118,6 +118,12 @@ function ReadableState(options, stream, isDuplex) {
this.endEmitted = false;
this.reading = false;
// Stream is still being constructed and cannot be
// destroyed until construction finished or failed.
// Async construction is opt in, therefore we start as
// constructed.
this.constructed = true;
// A flag to be able to tell if the event 'readable'/'data' is emitted
// immediately, or on a later tick. We set this to true at first, because
// any actions that shouldn't happen until "later" should generally also
@ -197,9 +203,16 @@ function Readable(options) {
if (typeof options.destroy === 'function')
this._destroy = options.destroy;
if (typeof options.construct === 'function')
this._construct = options.construct;
}
Stream.call(this, options);
destroyImpl.construct(this, () => {
maybeReadMore(this, this._readableState);
});
}
Readable.prototype.destroy = destroyImpl.destroy;
@ -461,11 +474,12 @@ Readable.prototype.read = function(n) {
}
// However, if we've ended, then there's no point, if we're already
// reading, then it's unnecessary, and if we're destroyed or errored,
// then it's not allowed.
if (state.ended || state.reading || state.destroyed || state.errored) {
// reading, then it's unnecessary, if we're constructing we have to wait,
// and if we're destroyed or errored, then it's not allowed,
if (state.ended || state.reading || state.destroyed || state.errored ||
!state.constructed) {
doRead = false;
debug('reading or ended', doRead);
debug('reading, ended or constructing', doRead);
} else if (doRead) {
debug('do read');
state.reading = true;
@ -587,7 +601,7 @@ function emitReadable_(stream) {
// However, if we're not ended, or reading, and the length < hwm,
// then go ahead and try to read some more preemptively.
function maybeReadMore(stream, state) {
if (!state.readingMore) {
if (!state.readingMore && state.constructed) {
state.readingMore = true;
process.nextTick(maybeReadMore_, stream, state);
}