1

I am trying to keep adding numbers in a loop as shown in the code below:

const readline = require('readline');

const askOnCommandLine = (question) =>
  new Promise((resolve) => {
    const p = readline.createInterface({
      input: process.stdin,
      output: process.stdout,
      prompt: question,
    });

    p.on('line', (input) => {
      resolve(input);
    });

    p.prompt();
  });

let counter = 0;

(async () => {
  while (true) {
    console.log('Loop:', counter);
    const number1 = await askOnCommandLine('Enter 1st number: ');
    const number2 = await askOnCommandLine('Enter 2nd number: ');
    console.log('Addition:', parseInt(number1) + parseInt(number2));
    counter += 1;
  }
})();

But there are two problems here:

  1. It prints a single key press multiple times as shown in the screenshot.

Loop: 1 Shows that first number is 222 but it actually just 2

  1. After a few loops, there an error as follows:
Enter 2nd number:
(node:706492) MaxListenersExceededWarning: Possible EventEmitter memory leak detected.
11 end listeners added to [ReadStream]. Use emitter.setMaxListeners() to increase limit
(Use `node --trace-warnings ...` to show where the warning was created)
thewebjackal
  • 785
  • 8
  • 17
  • 1
    You're calling `readline.createInterface()` multiple times without finishing the previous ones. `p.close()` will close a previous one so you have multiple ones opens on the same streams. But, really, you wouldn't normally create a new interface every time you want to ask the next question. That's what `rl.prompt()` or `rl.question()` are for. – jfriend00 Jan 01 '22 at 18:13

1 Answers1

2

Just like event listeners in the browser, you need to be dealing with these stream interfaces after you're done with them, otherwise they'll just keep building up in memory (hence the warning and the unexpected behavior). It looks like readline exposes a close() method, why not close the stream when you're done with it?

const askOnCommandLine = (question) =>
  new Promise((resolve) => {
    const p = readline.createInterface({
      input: process.stdin,
      output: process.stdout,
      prompt: question,
    });

    p.on('line', (input) => {
      resolve(input);
      p.close();
    });

    p.prompt();
  });
Brendan Bond
  • 1,737
  • 1
  • 10
  • 8
  • I was about to answer my own question after going through the docs. But you have already done it. This is the accepted answer. Also, I have switched from p.on to p.question. – thewebjackal Jan 01 '22 at 18:31