Print without a newline in Node.js
Use stdout.write for inline output, update terminal progress safely, and account for redirected output and stream backpressure.
Use process.stdout.write() when you need output without an automatically appended newline:
process.stdout.write('Hello, ');
process.stdout.write('world!');
process.stdout.write('\n');
Unlike console.log(), write() does not add a line ending. It accepts a string or supported byte data, not console-style formatting arguments. Convert a number with String(value) or interpolate it into a string.
Update a progress line
A carriage return, \r, moves the cursor to the beginning of the current line on a typical terminal. It does not erase text left over from a longer previous message. Node's readline helpers make clearing and repositioning explicit:
// progress.mjs
import { cursorTo, clearLine } from 'node:readline';
import { setTimeout as delay } from 'node:timers/promises';
for (let percent = 0; percent <= 100; percent += 20) {
const message = `Progress: ${percent}%`;
if (process.stdout.isTTY) {
cursorTo(process.stdout, 0);
clearLine(process.stdout, 0);
process.stdout.write(message);
} else {
process.stdout.write(message + '\n');
}
await delay(100);
}
if (process.stdout.isTTY) process.stdout.write('\n');
The TTY check keeps terminal-control sequences out of an ordinary redirected log. Terminal capabilities still vary, including on Windows, so use a terminal-aware progress library when you need richer interaction.
stdout, stderr, and shell redirection
Use process.stderr.write() for diagnostic output that should remain separate from the program's normal result. Both streams follow the destination supplied by the process launcher. For example, node progress.mjs > progress.log sends stdout to a file, where a sequence of plain progress lines is more useful than cursor movement.
console.log() remains convenient for ordinary log lines and object formatting. console.error() writes through stderr. Switching to stdout.write is about controlling output, not a guarantee of better performance.
Backpressure and process exit
For a few short messages, direct writes are straightforward. For sustained output, write() returning false means the producer should wait for the stream's drain event before continuing. Handle stream errors as well; a downstream process may close its pipe early.
Avoid forcing process.exit() immediately after buffered output. Setting process.exitCode and letting the event loop finish gives pending work a chance to complete. This does not protect against abrupt termination or destination errors. stdout and stderr can perform synchronous or asynchronous writes depending on the operating system and destination, so a large volume of output can affect application latency.
See process I/O and readline cursor helpers.
Contact us
Join the community
to join the community
Try Guance
Start online and pay only for what you use.
Get startedChoose a Guance plan