Skip to content

Commit

Permalink
doc: fix unsafe writable stream code example
Browse files Browse the repository at this point in the history
Update writable stream code example using async iterator to use safer
`finished()` method instead of a `finish` event to avoid uncaught
exceptions

Fixes: #29397

PR-URL: #29425
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
  • Loading branch information
ckarande authored and targos committed Sep 20, 2019
1 parent 735ef8b commit 32bb58b
Showing 1 changed file with 26 additions and 6 deletions.
32 changes: 26 additions & 6 deletions doc/api/stream.md
Original file line number Diff line number Diff line change
Expand Up @@ -2556,6 +2556,7 @@ it is important to ensure the correct handling of backpressure and errors.

```js
const { once } = require('events');
const finished = util.promisify(stream.finished);

const writable = fs.createWriteStream('./file');

Expand All @@ -2567,26 +2568,45 @@ const writable = fs.createWriteStream('./file');
}
writable.end();
// Ensure completion without errors.
await once(writable, 'finish');
await finished(writable);
})();
```

In the above, errors on the write stream would be caught and thrown by the two
`once()` listeners, since `once()` will also handle `'error'` events.
In the above, errors on `write()` would be caught and thrown by the
`once()` listener for the `'drain'` event, since `once()` will also handle the
`'error'` event. To ensure completion of the write stream without errors,
it is safer to use the `finished()` method as above, instead of using the
`once()` listener for the `'finish'` event. Under certain cases, an `'error'`
event could be emitted by the writable stream after `'finish'` and as `once()`
will release the `'error'` handler on handling the `'finish'` event, it could
result in an unhandled error.

Alternatively the readable stream could be wrapped with `Readable.from()` and
Alternatively, the readable stream could be wrapped with `Readable.from()` and
then piped via `.pipe()`:

```js
const { once } = require('events');
const finished = util.promisify(stream.finished);

const writable = fs.createWriteStream('./file');

(async function() {
const readable = Readable.from(iterator);
readable.pipe(writable);
// Ensure completion without errors.
await once(writable, 'finish');
await finished(writable);
})();
```

Or, using `stream.pipeline()` to pipe streams:

```js
const pipeline = util.promisify(stream.pipeline);

const writable = fs.createWriteStream('./file');

(async function() {
const readable = Readable.from(iterator);
await pipeline(readable, writable);
})();
```

Expand Down

0 comments on commit 32bb58b

Please sign in to comment.