9

I'm trying to use the node.js package readline to get user input on the command line, and I want to pipe the entered input through promises. However, the input never gets through the then chain. I think the problem could come from the fact that the promises are fulfilled in the callback method, but I don't know how to solve that problem.

An example of this problem looks like this:

import rlp = require('readline');

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

let prom = new Promise(resolve => {
  rl.question('Enter input: ', input => rl.close() && resolve(input));
});

prom
  .then(result => { console.log(result); return prom; })
  .then(result => { console.log(result); return prom; })
  .then(result => console.log(result));

If run in node.js, the question will appear once, after input has been entered the program just stops. I want it to wait until the first input has been entered, then it should print this input and ask for the next input.

Thanks in advance!

Jurosh
  • 6,984
  • 7
  • 40
  • 51
Lukas Bach
  • 3,559
  • 2
  • 27
  • 31
  • Why are you trying to reuse the very same promise instead of just creating a new one inside a `while` loop? Take a look at my answer here https://stackoverflow.com/a/46488389/941240 – Wiktor Zychla Dec 27 '17 at 21:46

5 Answers5

21

Once your promise is resolved, there's no use of waiting for that again. I also moved the rl.close() call to the end, as it's needed to be called only once.

const rlp = require('readline');

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

function ask() {
  return new Promise(resolve => {
    rl.question('Enter input: ', input => resolve(input));
  });
}

ask()
  .then(result => { console.log(result); return ask(); })
  .then(result => { console.log(result); return ask(); })
  .then(result => { console.log(result); rl.close() });
Jurosh
  • 6,984
  • 7
  • 40
  • 51
Bence Gedai
  • 1,461
  • 2
  • 13
  • 25
7

Node.js 17 is here with new promise-based APIs for readline module:

import { createInterface } from 'node:readline/promises'
import { stdin, stdout } from 'process'

const rl = createInterface({ input: stdin, output: stdout })

const answer = await rl.question('What do you think of Node.js? ')

console.log('Thank you for your valuable feedback:', answer)

rl.close()

https://nodejs.org/api/readline.html#readline

Mir-Ismaili
  • 13,974
  • 8
  • 82
  • 100
  • 1
    When i try to use promises shows the following error message: Cannot find module 'node:readline/promises' or its corresponding type declarations.ts(2307) – Victor Guedes May 23 '22 at 18:26
  • @VictorGuedes; Which version of node.js do you use? Try `import * as readline from 'readline/promises'`. – Mir-Ismaili May 24 '22 at 09:18
4

Here's an answer from this question here for which I deserve no credit.


// Function
function Ask(query) {
  const readline = require("readline").createInterface({
    input: process.stdin,
    output: process.stdout
  })

  return  new Promise(resolve => readline.question(query, ans => {
  readline.close();
  resolve(ans);
}))
}

 
// example useage
async function main() {

 var name = await Ask("whats you name")
 console.log(`nice to meet you ${name}`)

 var age = await Ask("How old are you?")
 console.log(`Wow what a fantastic age, imagine just being ${age}`)
}

main()
Max Carroll
  • 4,441
  • 2
  • 31
  • 31
3

const readline = require('readline');

const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
const ask = (query) => new Promise((resolve) => rl.question(query, resolve));

ask('A: ').then(async (a) => {
  const b = await ask('B: ');
  const c = await ask('B: ');

  console.log(a, b, c);

  rl.close();
});

rl.on('close', () => process.exit(0));

0

node prompt.mjs

import { createInterface as createQuestionInterface } from 'readline';

const rl = createQuestionInterface({
  input: process.stdin,
  output: process.stdout
});

function questionLine(multiline, resolve, i, input, rl) {
  if (!multiline) {
    resolve(i);
  } else {
    if (input && !i) {
      resolve(input);
    } else {
      return input + i + "\r\n";
    }
  }
  return input;
}

function promptMultiLine(questionText) { // This is async by returning promise
  return prompt(questionText, true);
}

async function prompt(questionText, multiline = false) {
  return await (new Promise((resolve, reject) => {
    let input = '';
    rl.question(`${questionText}: `, (i) => {
      input = questionLine(multiline, resolve, i, input, rl);
    });
    rl.on('line', (i) => {
      input = questionLine(multiline, resolve, i, input, rl);
    });
  }));
}

async function run() {
  const question = prompt("please enter response [enter to complete]");
  console.log(question);
  const questionMultiLine = promptMultiLine("please enter response [enter text and enter twice]");
  console.log(questionMultiLine);
}

run();
TamusJRoyce
  • 817
  • 1
  • 12
  • 25