Search code examples
javascriptnode.jsreadline

Node.js - How to store readline answer in a variable


I am constructing a Yahtzee in node.js. I use below code to ask user for input. The answer needs to be stored in a variable. I assume [answer] is used to temporarily store the answer value, but how can I get out the [answer] to an array without to many change of the code structure ?

Basic code structure:

const readline = require('readline');

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

rl.question("Which dices to keep [1,2,3,4,5] ?: ", (answer) => {
  console.log("Will keep dices: ", answer);
  rl.close();
});

Extended basic code structure, to add the user input answer, into a variable:

var lines;                                 // Added compared to basic code.
const readline = require('readline');
const rl = readline.createInterface({
  input:  process.stdin,
  output: process.stdout
});
rl.question("Which dices to keep [1,2,3,4,5] ?: ", (answer) => {
  lines.push(answer);                      // Added compared to basic code.
  console.log("Will keep dices: ", answer);
  rl.close();
});
console.log(lines);                        // Added compared to basic code.

Result from terminal: Undefined.


Solution

  • That's not really how this works - with asynchronous operations like user input, it's expected that you will handle the outcome in a callback, rather than "waiting" for completion. One thing you can do is wrap your code in a Promise, like this:

    const readline = require('readline');
    
    function getDiceAnswer() {
        return new Promise(resolve => {    
            const rl = readline.createInterface({
                input:  process.stdin,
                output: process.stdout
            });
            rl.question("Which dices to keep [1,2,3,4,5] ?: ", (answer) => {
                resolve(answer);
                console.log("Will keep dices: ", answer);
                rl.close();
            });
        });   
    }
    

    This still means you need to deal with a result in a callback:

    const lines = [];
    getDiceAnswer().then(answer => {
         lines.push(answer);
         console.log(lines);
    });
    

    ...but you can use Javascript async/await notation to make it look nicer:

    async function getAnswers() {
         const diceAnswer = await getDiceAnswer();
    
         //this line won't execute until the answer is ready
         lines.push(diceAnswer);
    }
    

    Another, simple alternative is to use a pacakge like readline-sync to make the action a synchronous one: https://www.npmjs.com/package/readline-sync