Stealthmate
Stealthmate

Reputation: 167

NodeJS readline sometimes prints back first input line (but not always, seems random)

So I'm using this example code from the NodeJS docs:

const readline = require('readline');
const rl = readline.createInterface(process.stdin, process.stdout);
console.log("Hello!");
rl.setPrompt('OHAI> ');
rl.prompt();

rl.on('line', (line) => {
  switch(line.trim()) {
    case 'hello':
      console.log('world!');
      break;
    default:
      console.log('Say what? I might have heard `' + line.trim() + '`');
      break;
  }
  rl.prompt();
}).on('close', () => {
  console.log('Have a great day!');
  process.exit(0);
});

I'm on Windows, running NodeJS 6.0.0. When I run the file, it writes "Hello!", followed by the first "OHAI> ". So far so good. Now I try writing an arbitrary "asd". When I press enter, one of two things happens:

  1. It prints:

asd

Say what? I might have heard 'asd'

OHAI>

  1. It prints

Say what? I might have heard 'asd'

OHAI>

This only happens on the first input line. It seems to be completely random, however if, after I type node test.js, I press enter fast enough, sometimes I get a newline before the first "OHAI> " and it doesn't print my arbitrary input.

Is there something wrong with the example? Is it a bug in NodeJS? Even if it can't be fixed, I'd be relieved to know what causes it, since I've been pulling my hairs out for hours now.

Upvotes: 4

Views: 2323

Answers (2)

ShadowFax
ShadowFax

Reputation: 421

This should solve the issue.

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

Upvotes: 16

Stealthmate
Stealthmate

Reputation: 167

I'm still not sure why this happens, but I've found a way around it. It's a bit ugly, but it does the job.

var rl;
function cli() {
    const readline = require('readline');
    rl = readline.createInterface(process.stdin, process.stdout);
    rl.prompt();
    rl.on('line', exec_cmd);
    rl.on('close', () => {
        console.log('And now we part company.');
        process.exit(0);
    });
}
function fixfunc() {
    //get first input
    var input = process.stdin.read();
    if (input == null)
        return;
    input = input.toString("utf-8");
    //No longer needed, so remove the listener
    process.stdin.removeListener('readable', fixfunc);
    process.stdin.resume();
    //do whatever you want with the input
    exec_cmd(input);
    //Initialize readline and let it do its job
    cli();
}
process.stdin.pause();
process.stdin.on('readable', fixfunc);
process.stdout.write("> Welcome, Commander!\n> ");

What this basically does, is pause stdin, get the first input, manually call the parsing function and then initalize readline and let it do its job.

Upvotes: 0

Related Questions