node.js的console.log是异步的吗?


95

console.log/debug/warn/error在node.js中-异步?我的意思是,直到代码在屏幕上打印出来,否则javascript代码执行都会停止执行,还是稍后再打印?

另外,我有兴趣知道console.log是否有可能在节点崩溃后立即不显示任何内容。

Answers:


102

更新:从Node 0.6开始,此帖子已过时,因为stdout 现在是同步的

好吧,让我们看看console.log实际是什么。

首先,它是控制台模块的一部分:

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

因此,它只是进行一些格式化并写入process.stdout,到目前为止还没有异步。

process.stdout在启动时定义的吸气剂它是惰性初始化的,我添加了一些注释来解释事情:

.... 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;
});

在使用TTY和UNIX的情况下,我们到这里结束,这件事是从套接字继承的。因此,节点基本上要做的就是将数据推送到套接字上,然后由终端负责其余的工作。

让我们测试一下!

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);

结果

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

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

终端需要大约1秒钟来打印套接字内容,而节点仅需要17毫秒即可将数据推送到终端。

流情况也是如此,文件情况也将异步处理。

因此,是的, Node.js遵守其非阻塞承诺。


2
更新:在标准输出node.js的是现在同步:groups.google.com/group/nodejs/browse_thread/thread/...
dhruvbird


@IvoWetzel我现在不得不对此进行投票,因为它已经过时了。
埃文·卡罗尔

我知道这已经过时了,但是process.stdout.write()write()定义为异步之后,您会立即说“到目前为止还没有异步”
binki

26

console.warn()和console.error()被阻止。在基础系统调用成功之前,它们不会返回。

是的,在刷新写入stdout的所有内容之前,程序可能会退出。即使仍然有对stdout的写入队列,process.exit()也会立即终止节点。您应该使用console.warn避免这种现象。


1
对于Windows中的节点0.10.25,情况并非如此。console.warn()console.error()具有与相同的非阻塞行为console.log()Windows中甚至有一个软件包可以解决该问题
Lucio Paiva 2014年

12

我的结论,在阅读完Node.js 10. *文档之后(如下)。是您可以使用console.log进行日志记录,console.log是同步的,并在低级c中实现。尽管console.log是同步的,但仅当您不记录大量数据时,它才不会导致性能问题。

(下面的命令行示例演示了console.log 异步和console.error为sync

基于Node.js Doc的

当目标是终端或文件时,控制台功能是同步的(以避免过早退出时丢失消息),而在管道时则是异步的(以避免长时间阻塞)。

也就是说,在以下示例中,stderr处于阻塞状态时stdout是非阻塞的:

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

在日常使用中,除非您>记录大量数据,否则不必担心阻塞/非阻塞二分法。

希望能帮助到你


什么是“大量数据”?它是由对console.log的调用次数还是要写入的总数定义的?什么是巨大的1KB / ms,1MB / ms,1GB / ms?
MattG

3

Console.log在Windows中是异步的,而在linux / mac中是同步的。要使Windows中的console.log同步,可能在index.js文件的代码开头写入此行。该语句之后的任何console.log都将被解释器视为同步。

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

顺便说一句,Linux不仅仅是Ubuntu。
ozanmuyes

谢谢,不好意思,但是Debian是我的弱点,并且现在每个开始使用Linux的人似乎都认为Ubuntu Linux(除了您,我知道您不是其中之一)。祝您有美好的一天:)
ozanmuyes
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.