-
Notifications
You must be signed in to change notification settings - Fork 80
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
Streams aren't implemented according to Node.js documentation #110
Comments
oh cool. Yes, there's a reason the spec hasn't been followed: this feature was written before node v8 was released. I even wrote this post on stackoverflow complaining about the lack of a destroy api: https://stackoverflow.com/a/34548102/367916 (and then updated it just now to mention that a formal api exists now). This library supports very old versions of node, so there would need to be some kind of conditional override. This complexity will have some rippling effects elsewhere in the API as well. Can you give an example of the async iteration that breaks without the proper destroy api? |
Ah right. Interesting. Simple repro below: // specifics of next three lines not important
const zip = await openZip('/path/to/zip');
const entry = await getEntry(zip);
const stream = await openReadStream(entry);
for await (const chunk of stream) {
throw new Error('BANG!');
} The above for-await-of translates roughly to the following: const iterator = stream[Symbol.asyncIterator]();
let item;
try {
for (; item = await iterator.next(), !item.done;) {
throw new Error('BANG!');
}
} finally {
if (item && !item.done && iterator.return) {
// we ended prematurely, so call iterator.return if it exists
await iterator.return();
}
} The readable stream implementation has the following definition for return() {
// destroy(err, cb) is a private API.
// We can guarantee we have that here, because we control the
// Readable class this is attached to.
return new Promise((resolve, reject) => {
this[kStream].destroy(null, (err) => {
if (err) {
reject(err);
return;
}
resolve(createIterResult(undefined, true));
});
});
} Because your |
This has been fixed by nodejs/node#29176 in node 12.10. For earlier versions I'm getting round it by piping through an echo stream first: class EchoStream extends stream.Transform {
constructor() {
super({
transform: (data, encoding, callback) => {
callback(null, data);
},
});
}
} This provides a 'real' stream implementation for consumers. |
I did my best to work around the |
According to the Node.js docs stream implementations should override
_destroy
and notdestroy
as you have, and they should accept a second parameter which is a callback. Without the callback, async iteration breaks.I can contribute a PR unless there's a reason the spec hasn't been followed?
The text was updated successfully, but these errors were encountered: