2022-10-16

Why does Javascript readline question method read more than one line when wrapped in a Promise

Why does Javascript readline question method read more than one line when wrapped in a Promise?

The code below is supposed to simply add line numbers to the input. It works as expected if I run it and type the input at the command line. However, if I redirect a file into the process, then it consumes the entire file at once. Why is that?

Expected output:

Next line, please: File line 1
1       File line 1
Next line, please: File line 2
2       File line 2
Next line, please: File line 3
3       File line 3
Next line, please: File line 4
4       File line 4
Next line, please: Input stream closed.

Observed output (when running node testReadline.mjs < the_file.txt)

Next line, please: File line 1
File line 2
File line 3
File line 4
1       File line 1
Next line, please: Input stream closed.

It appears to be consuming the entire file after the first call to question, rather than consuming only one line at a time.

(I know there is the readline/promises package. I'm curious why the code below doesn't behave as expected.)

import * as readline from 'node:readline';

const io = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
  });

io.on('close', () => {console.log("Input stream closed.")});

let questionWrapper = (prompt) => {
    return new Promise((resolve, reject) => {
        io.question(prompt, (line) => {
            resolve(line)
        });
    });
}

let printLine_await = async () => {
    let line_num = 1;
    while(true) {
        let line = await questionWrapper('Next line, please: ');
        console.log(`${line_num}\t${line}`)
        line_num++;
    }
}

printLine_await(1)

For what it's worth, I get the expected result when using callbacks.

This code

let printLine_callback = (line_num) => {
    io.question('Next line, please: ', (line) => {
        console.log(`${line_num}\t${line}`)
        printLine_callback(line_num + 1)
    })
}

Produces this result:

Next line, please: File line 1
1       File line 1
Next line, please: File line 2
2       File line 2
Next line, please: File line 3
3       File line 3
Next line, please: File line 4
4       File line 4
Next line, please: Input stream closed.

It's not clear from the documentation what is supposed to happen if the input ends while question is waiting; but, the behavior I see makes sense in this case (where the file ends with a newline).



No comments:

Post a Comment