Home > front end >  Why console.log in a loop stops printing when piping to another command?
Why console.log in a loop stops printing when piping to another command?

Time:09-10

I'm using fake-words module (npm install fake-words) with the following simple code:

#!/usr/bin/env node
const fake = require("fake-words");
while (true) {
  console.log(fake.sentence());
}

When I run ./genwords.js, everything works as expected.

However when I pipe into external program (on Ubuntu shell), the generation of words stops after a second.

$ ./genwords.js | cat
...
(output generation stops after a second)
$ ./genwords.js | tee
...
(stuck as well)
$ ./genwords.js | pv -l
...
4.64k 0:00:13 [0.00 /s]

Same happening when assigning a value to variable to avoid any caching (as precaution after reading this post, probably not relevant to Node.js):

while (true) {
  words = fake.sentence();
  console.log(words);
}

What I'm doing wrong?

I'm using Node v16 on Ubuntu:

$ node --version
v16.13.1

CodePudding user response:

The behavior of console.log() in code (such as the while loop in your example) that never relinquishes control to the event loop (especially when piped to another process) in Node.js is a longstanding...uh...quirk. It's a lot harder to fix than you might think. Here's the relevant issue in the tracker: https://github.com/nodejs/node/issues/6379

Or more specifically on the whole handling-when-piped-to-another-process issue: https://github.com/nodejs/node/issues/1741

You can work around the issue by restructuring the code to relinquish control to the event loop. Here is one possibility.

#!/usr/bin/env node
const fake = require("fake-words");

function getWords() {
  console.log(fake.sentence());
  setImmediate(getWords);
}

getWords()
  • Related