user6689821 user6689821 - 1 year ago 185
Node.js Question

readline.write() does not arrive at stdout

I'm trying to write a test for a CLI that uses Node.js's readline module to print and capture info from the user, and I can't seem to capture anything from stdout. A simple version of the issue I'm facing follows.


#!/usr/bin/env node

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



const spawn = require('child_process').spawn

const rl = spawn(__dirname + '/app.js')

rl.stdout.on('data', chunk => {
console.log('stdout says', chunk.toString())

, I would expect to see the output
stdout says hello
, but nothing prints.

However, if I run
prints out to the console. Additionally, if I use other readline methods such as
, the handler will fire with the expected data.

Why doesn't this code work as expected? How can it be changed to work?

Answer Source

Relate to Readline output to file Node.js

To capture the output of rl.write(), one solution is: define "terminal" as true when creating readline interface instance.

Sample code:

const readline = require('readline');
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
  terminal: true

Explanation: readline module in node.js only write data to the "output" stream when "terminal" is true. Otherwise, it just emit "line" event, and send data to the line event handler. According to the source code (

First, Check whether "terminal" is configured. If not, make it equal to output stream's isTTY property:

if (terminal === undefined && !(output === null || output === undefined)) {
  terminal = !!output.isTTY;
this.terminal = !!terminal;

Second, when rl.write() function is invoked, it will call _ttyWrite() or _normalWrite(), depending on whether "terminal" is true:

Interface.prototype.write = function(d, key) {
  this.terminal ? this._ttyWrite(d, key) : this._normalWrite(d);

Finally, if _ttyWrite() is called, data will be sent to output stream. If _normalWrite() is called, output stream is ignored:

//Interface.prototype._ttyWrite will invoke Interface.prototype._insertString, which will call Interface.prototype._writeToOutput
Interface.prototype._writeToOutput = function _writeToOutput(stringToWrite) {
  if (this.output !== null && this.output !== undefined)

Thus, when app.js is run in console directly, "hello" will be printed, as "terminal" is equal to process.stdout.isTTY, which is true. However, when executed in child process, "terminal" is false (if not configured), as process.stdout.isTTY is undefined now.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download