Reading From Console

16 July 2019 - 64 views
Node.Js provides several ways to read user input from the terminal. This article explains how to use the process object to read user input. The process object is a global object which is available without the need to include it using the require() method.

To read user input, you need to access the stdin property, which returns a Stream. Since all streams are an instance of EventEmitter, we can use the on() method to monitor the data event as shown in listing 1 below.

Listing 1

process.stdin.setEncoding("utf8");
process.stdin.on("data"(data) => {
    console.log("You typed", data.trim());
});

When a user presses the enter button, the data event triggers the callback function, passing in the data that was entered. The data includes the new line character, which is why the trim() function is used to remove it. So now you know how to read your input, let's take a look at a simple program that asks the user a series of questions and stores the answers in an array.

Listing 2

const questions = [];
questions.push("What is your first name?");
questions.push("What is your last name?");
questions.push("What is your age?");

const answers = [];

printQuestion();

process.stdin.setEncoding("utf8");
process.stdin.on("data"(data) => {

    let input = data.trim();

    if(input !== ""){
        answers.push(input);
    }

    printQuestion();
});

function printQuestion(){
    if(answers.length == questions.length){
        printSummary();
    }else{
        console.log(questions[answers.length]);
    }
}

function printSummary(){
    questions.forEach((question, index) => {
        console.log(question, answers[index]);
    });
}

The code in listing 2 above creates two arrays (questions and answers). When the user enters data, the data event is triggered and checks if the user input is not empty. If the input is not empty, it is added to the answers array, which increases the array length. The printQuestion() function is then called. This function uses the length of the answers array to determine if it is equal to the length of the questions array. If it is, the printSummary() function is called. If it isn't, then the next question is shown by using the length of the answers array as the index position for the questions array.

An alternative to using the process object is to use the readline module, which is part of the default NodeJs installation.

Bonus


The code in listing 3 below, shows a complete program for a simple Hangman game. The game initializes with a random word selected from a list of predefined words. You have 10 attempts to guess the word or you lose and a new game is generated.

Listing 3

// List of playing words.
const words = [
    "house",
    "train",
    "hotel",
    "window",
    "computer",
    "laptop",
    "forest",
    "telephone",
    "apple",
    "orange",
    "banana"

];

// Contains an array of characters from the selected word.
var wordArray;
// Contains an array of correct characters entered by user.
var inputArray;
var attempts;

start();
showWordBar();

process.stdin.setEncoding("utf8");
process.stdin.on("data"(data) => {

    let input = data.trim();

    // Check input, only one character allowed.
    if(input == "" || input.length > 1){
        console.log("Please enter a single character.");
    }else{
        // Does input char exist in selected word array?
        if(wordArray.includes(input)){
            // Find all input chars.
            findAll(input);
        }else{
            // Increment failed attempt.
            attempts +=1 ;

            // 10 failed attempts? I guess you lost.
            if(attempts === 10){
                console.log("Opps, you lost.");
                // Start a new word game.
                start();
            }else{
                // Not many attempts left. Yikes.
                console.log("Incorrect. You have"(10 - attempts)"attempts left.");
            }
        }
    }
    // Show the ----- bar
    showWordBar();

    // Does the input character array contain "-" (dash).
    // No dashes? Well I guess you won.
    if(!inputArray.includes("-")){
        console.log("You win. Well done.");
        start();
        showWordBar();
    }
});

function start(){
    console.log("Generating a new word.");
    wordArray = getWordArray();
    inputArray = getInputArray();
    attempts = 0; 
}

function getWordArray(){
    let rand = parseInt(Math.random() * words.length);
    return words[rand].split("");
}

function getInputArray(){
    return "-".repeat(wordArray.length).split("");
}

function findAll(input){
    wordArray.forEach((v, i) => {
        if(input === v){
            inputArray[i] = input;
        }
    });
}

function showWordBar(){
    console.log(inputArray.join(""));
}