This is a little-known way to console log without newline that many developers have never used.
Let’s say we need to log in a loop like this:
for (let i = 1; i <= 5; i++) {
// print number without newline
}
// Output: 1 2 3 4 5
❌ Unfortunately the normal way fails us:
So what do we do?
What we do: is process.stdout.write
:
for (let i = 1; i <= 5; i++) {
process.stdout.write(`${i} `);
}
// Output: 1 2 3 4 5
How is process.stdout.write
different from console.log
?
Well first of all, console.log
IS process.stdout.write
!
stdout
is the fundamental way every CLI program logs output to the console.
That’s what it uses at its core:
Console.prototype.log = function() {
this._stdout.write(util.format.apply(this, arguments) + '\n');
};
But this extra processing makes it so much better for formatting:
- I can easily inspect objects with
console.log
withoutJSON.stringify
:
But process.stdout.write
fails miserably — it only accepts strings and Buffers:
But there’s something incredible only process.stdout.write
can do:
Data streaming:
process.stdout
is actually, a stream.
Streams represent data flow in Node.
- Read streams — data coming from
- Write streams — data going into
- Duplex streams — both
Data’s flowing from the file read stream into the stdout stream.
It’s the same as this:
import fs from 'fs';
fs.createReadStream('codingbeautydev.txt').on(
'data',
(chunk) => {
process.stdout.write(chunk);
}
);
But pipe
is much more natural for stream-to-stream data flow:
Letting you create powerful transformation pipelines like this:
import fs from 'fs';
import { Transform } from 'stream';
// ✅ duplex stream
const uppercase = new Transform({
transform(chunk, encoding, callback) {
callback(null, chunk.toString().toUpperCase());
},
});
fs.createReadStream('codingbeautydev.txt')
.pipe(uppercase)
.pipe(process.stdout);
process.stdin
process.stdin
is the process.stdout
‘s input counterpart — a readable stream for user input.
So see how with a single line I create a pipeline to reflect all my input to me:
process.stdin.pipe(process.stdout);
And when I insert the uppercase transformation into the pipeline:
import fs from 'fs';
import { Transform } from 'stream';
// ✅ duplex stream
const uppercase = new Transform({
transform(chunk, encoding, callback) {
callback(null, chunk.toString().toUpperCase());
},
});
process.stdin.pipe(uppercase).pipe(process.stdout);
process.stderr
Here to complete the standard stream trio.
console.log
→process.stdin
console.error
→process.stderr
Probably also defined this way in Node:
Console.prototype.error = function() {
this._stderr.write(util.format.apply(this, arguments) + '\n');
};
console.log('A normal log message');
console.error('An error message');
You can see the difference in the browser:
Although not much difference on Node:
These are 3 powerful streams that let you input, process, and output data creatively and intuitively.
11 Amazing New JavaScript Features in ES13
This guide will bring you up to speed with all the latest features added in ECMAScript 13. These powerful new features will modernize your JavaScript with shorter and more expressive code.