back

Interacting with the Console in Node.js

5 min read

Node.js provides the low-level interaction with the operating system particularly through input and output (I/O) operations. It includes core APIs that allows developer to handle with I/O streams, interact with the file system and manage the networking tasks efficiently. In this article, we will focus on interacting the console by exploring how to read and write input from the user and handle errors.

Interacting with Console

Before delving into the file system, we’re going to learn how to handle input with stdin, write output to stdout and log errors to stderr. Standard in (stdin) refers to an input stream that a program can use to read input from a Command Shell or Terminal. Also, Standard out (stdout) refers to the stream that is used to write the output. Lastly, Standard error (stderr) is a separate stream to log output data and diagnostic data.

Let’s create a file called greeting.js for user input via stdin, return via stdout and log an error to stderr when an input is invalid. First, we need to tell the program to listen the user input. This can be done by adding the following codes to the greeting.js.

console.log("What's your name?");

process.stdin.on("data", (data) => {
  const name = data.toString().trim();
  process.stdout.write(`Hello ${name}`);
});

We can run the file using the following command. Now, the program listens for process.stdin data events.

node greeting.js

After that, we can type input to the program. When pressing Enter, it will return the input data.

node greeting.js
What's your name?
Alex
Hello Alex

Moreover, we can check if the input string is empty, we’ll log to stderr. Let’s change the file to the following code.

console.log("What's your name?");

process.stdin.on("data", (data) => {
  const name = data.toString().trim();

  if (name === "") {
    process.stderr.write("Input is empty!\n");
  } else {
    process.stdout.write(`Hello ${data}`);
  }
});

Restart the program again and press Enter with no input.

node greeting.js
What's your name?
Input was empty!

We’ve created a program that can read data from stdin, write data to stdout and log error to stderr.

How does it work?

The process.stdin, process.stdout, process.stderr are properties on the process object. A process object is a global object that provides information and control of the Node.js process. For each I/O (standard in, standard out, standard error), they emit data events for every chunk of data they received.

The process.stdin.on instance listens for these data events. Each data event return a Buffer object. The Buffer object returns a binary representation of the input. The const name = data.toString().trim(); instance turns the Buffer object into a string. The trim() function removes all whitespace characters including spaces, tabs and newline character.

Also, stdout and stderr uses the perspective properties on the process object. During the program, we also used Ctrl + C to exit the program in the terminal. Ctrl + C sends the signal called SIGINT which is known as signal interrupt to the Node.js process. For further information about signal events, we can reach out to the Node.js Process API documentation.

Alternative approach with readline

At the version 17.0.0, Node.js provides an Readline Promises API which is used for reading a file line by line. The Promises API allow us to use with async / await instead of callbacks which provides more modern and cleaner approach to handle asynchronous operations.

Here is the another example of a similar program to the greeting.js.

const readline = require("readline/promises");

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

  const name = await rl.question("What's your name?\n");
  console.log(`Hello ${name}`);
  rl.close();
}

greet();

This program utilizes the readline/promises module which provides the Promise variant of the Readline API. It defines the asynchronous function called greet() to prompt the user input in the console which is similar to the previous program. This appraoch uses the Readline Promises API with async / await syntax for cleaner asynchronous code.

We’ve explored how the Node.js handles the console interactions using process.stdin, process.stdout and process.stderr for user input, processes data and logs errors. Additionally, we’ve used readline/promises module which provides a modern and cleaner way to handle user input with asynchronous operations. Understanding these fundamental I/O mechanisms is essential for building more interactive and robust Node.js applications.