You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
awaiting between creating a readline interface, and using async iterator will cause iterator to sometimes skip. #33463
If you add some kind of await xxx() between creating the interface and iterating, the iterator will miss lines. In my case I input 100k lines from a file, then output those same lines to a new file. several thousand lines will go missing.
How often does it reproduce? Is there a required condition?
100%
Need to add some await async between creating the interface and using for await
So, there is no intent to ever actually "fix" this. You're just going to document it as is and leave it that way forever? So, no asynchronous operations are permitted between creating the interface and consuming the async iterator to read the lines? What if you're trying to use this along with some other asynchronous stuff together? That's just a busted implementation IMO. Documenting the existing behavior is OK for a stop-gap, but not really OK for just sweeping the issue under the rug forever.
Reacted by Govind Rai, bigdorak and Christian Koop
I agree with @jfriend00. This behaves like an improper implementation. Even after following the guidelines to prevent loss of line data, we are facing issues where have a function that is doing some heavy async operations on the result of each line (i.e. each line may take 5 or minutes to complete) and what we get is readline running some lines and eventually hanging and not issuing any more lines -> the program hangs forever.
async function heavyAsyncOperationsPerLine() {
const rl = readline.createInterface({ input: getReadStream() }); // this file has 800K lines
// called directly after
for await (const line of rl) {
await operation1()
await operation2()
}
}
Reacted by John Friend, Stella Hu and Christian Koop
@govindrai I think you might have encountered another bug
The original problem is due to how readline implements AsyncIterable: it usesEventEmitter.on() to create it. EventEmitter.on() has implementation that starts buffering events from the moment on() was called
If there's a delay between creating rl and calling rl[Symbol.asyncIterator]() (which is called internally by for await), EventEmitter.on() has not been called yet, so the lines read within the delay are not saved anywhere and won't be in the iterable
But I don't see how that can cause your issue
I though that maybe your problem was caused by memory leak/too many callbacks pending in the event loop, but the implementation seems to handle backpressure
Activity
devsnek commentedon May 19, 2020
readline isn't a stream, if you don't attach a handler you will miss events. that being said, exposing an async iterable doesn't make that very clear.
BridgeAR commentedon May 23, 2020
As @devsnek outlined there's nothing actually wrong with the behavior. We might want to improve our docs when it comes to that?
preyunk commentedon May 27, 2020
@devsnek @BridgeAR I would like to take up this issue, could you guide me through the process for achieving the same as I am a first time contributor.
jfriend00 commentedon Jul 13, 2020
Similar problem shown here: https://stackoverflow.com/questions/62885667/why-does-this-readline-async-iterator-not-work-properly.
I see only this output in the console:
The for await (const line1 of rl1) loop never goes into the for loop - it just skips right over it:
doc: add a note about possible missing lines to readline.asyncIterator
jfriend00 commentedon Aug 30, 2020
So, there is no intent to ever actually "fix" this. You're just going to document it as is and leave it that way forever? So, no asynchronous operations are permitted between creating the interface and consuming the async iterator to read the lines? What if you're trying to use this along with some other asynchronous stuff together? That's just a busted implementation IMO. Documenting the existing behavior is OK for a stop-gap, but not really OK for just sweeping the issue under the rug forever.
Trott commentedon Aug 30, 2020
@nodejs/readline Should this be re-opened?
doc: add a note about possible missing lines to readline.asyncIterator
govindrai commentedon Apr 9, 2021
I agree with @jfriend00. This behaves like an improper implementation. Even after following the guidelines to prevent loss of line data, we are facing issues where have a function that is doing some heavy async operations on the result of each line (i.e. each line may take 5 or minutes to complete) and what we get is readline running some lines and eventually hanging and not issuing any more lines -> the program hangs forever.
readline: buffer line events in async iterator
doc: add a note about possible missing lines to readline.asyncIterator
azerum commentedon Mar 10, 2025
@govindrai I think you might have encountered another bug
The original problem is due to how
readlineimplementsAsyncIterable: it usesEventEmitter.on()to create it.EventEmitter.on()has implementation that starts buffering events from the momenton()was calledIf there's a delay between creating
rland callingrl[Symbol.asyncIterator]()(which is called internally byfor await),EventEmitter.on()has not been called yet, so the lines read within the delay are not saved anywhere and won't be in the iterableBut I don't see how that can cause your issue
I though that maybe your problem was caused by memory leak/too many callbacks pending in the event loop, but the implementation seems to handle backpressure
doc: add a note about possible missing lines to readline.asyncIterator