-
Notifications
You must be signed in to change notification settings - Fork 31.1k
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
Problems with cooperation between async generator and stream #38487
Comments
Async generator is obviously in some "finished" state after let a = async function *() { yield "a"; };
let b = async function *() { yield "b"; };
let m = merge(a(), b());
for await (let chunk of m)
{
console.log(chunk);
break;
}
for await (let chunk of m)
{
console.log(chunk);
} |
See #38491 |
@nodejs/streams |
I would like to unpack this issue:
|
If I wrapped the body of |
Here is how you can use finally to implement this behavior: https://gist.github.com/mcollina/ad918bb6eb115ca86cf3e0f3c48d063f There are three ways in which you can implement this behavior with slightly different semantics. I think we should document those somewhere. cc @jasnell @benjamingr take a look. |
Actually I did not try try
{
do_something();
}
catch(e)
{
cleanup();
throw e;
}
cleanup(); try
{
do_something();
}
finally
{
cleanup();
} But similarity ends when there is a |
I don't feel I'm qualified to answer about the spec in this regard. Maybe others can step in and add references to the spec of this behavior. |
I think we can close this. |
Note this can still fail with badly behaving generators (the version that doesn't consume both generators to the end). One can write something like: async function* naughty() {
while (true) {
try {
yield 'foo';
} finally {
yield* naughty(); // .return runs finally blocks and the generator can just not finish
}
}
} Of course, for regular "streams" just destroying the stream in the finally in case it wasn't consumed is sufficient. I don't think Node.js can "fix" this on our side. I think the best path forward is the iterator-helpers proposal that should come with a merge function that guards against bad behaviours (maybe?). |
Sorry but which version do you mean? |
There hasn't been any activity here for a while and I believe this can be closed. Thanks for the discussion 🙏 |
Is your feature request related to a problem? Please describe.
Consider this simple async generator which is supposed to merge output of two input generators:
When using with file streams then second stream can be leaked by breaking or throwing from
for await
:Possible output:
At least the first stream is finished with premature close error but not the second.
Seems it is not possible to resolve this inside async generator itself. One possible solution would be to wrap it in stream and
destroy
input streams instream.finished()
callback and forget about returning async generator but return this stream instead for consumption:But this solution really does not feel right.
Describe the solution you'd like
It is probably not viable to track all streams used in an async generator and destroy them like one which is actually yielding. Maybe there could be added some "finally" handler for async generators. Or function like
streams.finished()
but for async generators (finished
accepts only streams now).Describe alternatives you've considered
Maybe should be reconsidered some aspects of node streams. Maybe file streams should not open files until something is trying to read it? Or streams could close file handle automatically (when they are garbage collected like in Python). (What about new
fs
apis that return async generators instead of streams?)The text was updated successfully, but these errors were encountered: