102

Are console.log/debug/warn/error in node.js asynchrounous? I mean will javascript code execution halt till the stuff is printed on screen or will it print at a later stage?

Also, I am interested in knowing if it is possible for a console.log to NOT display anything if the statement immediately after it crashes node.

6 Answers 6

110

Update: Starting with Node 0.6 this post is obsolete, since stdout is synchronous now.

Well let's see what console.log actually does.

First of all it's part of the console module:

exports.log = function() {
  process.stdout.write(format.apply(this, arguments) + '\n');
};

So it simply does some formatting and writes to process.stdout, nothing asynchronous so far.

process.stdout is a getter defined on startup which is lazily initialized, I've added some comments to explain things:

.... code here...
process.__defineGetter__('stdout', function() {
  if (stdout) return stdout;                            // only initialize it once 

  /// many requires here ...

  if (binding.isatty(fd)) {                             // a terminal? great!
    stdout = new tty.WriteStream(fd);
  } else if (binding.isStdoutBlocking()) {              // a file?
    stdout = new fs.WriteStream(null, {fd: fd});
  } else {
    stdout = new net.Stream(fd);                        // a stream? 
                                                        // For example: node foo.js > out.txt
    stdout.readable = false;
  }

  return stdout;
});

In case of a TTY and UNIX we end up here, this thing inherits from socket. So all that node bascially does is to push the data on to the socket, then the terminal takes care of the rest.

Let's test it!

var data = '111111111111111111111111111111111111111111111111111';
for(var i = 0, l = 12; i < l; i++) {
    data += data; // warning! gets very large, very quick
}

var start = Date.now();
console.log(data);
console.log('wrote %d bytes in %dms', data.length, Date.now() - start);

Result

....a lot of ones....1111111111111111
wrote 208896 bytes in 17ms

real    0m0.969s
user    0m0.068s
sys  0m0.012s

The terminal needs around 1 seconds to print out the sockets content, but node only needs 17 milliseconds to push the data to the terminal.

The same goes for the stream case, and also the file case gets handle asynchronous.

So yes Node.js holds true to its non-blocking promises.

Sign up to request clarification or add additional context in comments.

5 Comments

Update: stdout in node.js is now synchronous: groups.google.com/group/nodejs/browse_thread/thread/…
@IvoWetzel I'm going to have to downvote this now as it is obsolete.
I know this is obsolete and everything, but you say “nothing asynchronous so far” immediately after process.stdout.write() where write() is by definition asynchronous…
What about on Windows?
29

console.warn() and console.error() are blocking. They do not return until the underlying system calls have succeeded.

Yes, it is possible for a program to exit before everything written to stdout has been flushed. process.exit() will terminate node immediately, even if there are still queued writes to stdout. You should use console.warn to avoid this behavior.

1 Comment

This is not true for Node 0.10.25 in Windows. console.warn() and console.error() have the same non-blocking behaviour of console.log(). There's even a package to solve the problem in Windows.
13

My Conclusion , after reading Node.js 10.* docs (Attached below). is that you can use console.log for logging , console.log is synchronous and implemented in low level c . Although console.log is synchronic, it wont cause a performance issue only if you are not logging huge amount of data.

(The command line example below demonstrate, console.log async and console.error is sync)

Based on Node.js Doc's

The console functions are synchronous when the destination is a terminal or a file (to avoid lost messages in case of premature exit) and asynchronous when it's a pipe (to avoid blocking for long periods of time).

That is, in the following example, stdout is non-blocking while stderr is blocking:

$ node script.js 2> error.log | tee info.log

In daily use, the blocking/non-blocking dichotomy is not something you should worry about unless you > log huge amounts of data.

Hope it helps

2 Comments

What is a "huge amount of data"? Is it defined by number of calls to console.log or the total amount being written? What is a huge 1KB/ms, 1MB/ms, 1GB/ms?
such things are discovered by experimentations :) @MattG
3

Console.log is asynchronous in windows while it is synchronous in linux/mac. To make console.log synchronous in windows write this line at the start of your code probably in index.js file. Any console.log after this statement will be considered as synchronous by interpreter.

if (process.stdout._handle) process.stdout._handle.setBlocking(true);

Comments

2

You can use this for synchrounous logging:

const fs = require('fs')
fs.writeSync(1, 'Sync logging\n')

Comments

1

Came here while debugging a strange data issue. Data was being fetched from an endpoint, but when doing an immediate console.log()/warn()/error() in the API callback it looked different from what the network sent.

Turns out it's due to the async nature of console; something else, later on in the rendering, was mutating the object at the reference passed to log(). All while log() hadn't completed the printing.

Solution is to use JSON.Stringify or similar so that log() gets the current state of the object.

Hope this helps others coming here for the same situation.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.