Answers:
更新:从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遵守其非阻塞承诺。
process.stdout.write()
在write()
定义为异步之后,您会立即说“到目前为止还没有异步”
console.warn()和console.error()被阻止。在基础系统调用成功之前,它们不会返回。
是的,在刷新写入stdout的所有内容之前,程序可能会退出。即使仍然有对stdout的写入队列,process.exit()也会立即终止节点。您应该使用console.warn避免这种现象。
console.warn()
并console.error()
具有与相同的非阻塞行为console.log()
。Windows中甚至有一个软件包可以解决该问题。
我的结论,在阅读完Node.js 10. *文档之后(如下)。是您可以使用console.log进行日志记录,console.log是同步的,并在低级c中实现。尽管console.log是同步的,但仅当您不记录大量数据时,它才不会导致性能问题。
(下面的命令行示例演示了console.log 异步和console.error为sync)
当目标是终端或文件时,控制台功能是同步的(以避免过早退出时丢失消息),而在管道时则是异步的(以避免长时间阻塞)。
也就是说,在以下示例中,stderr处于阻塞状态时stdout是非阻塞的:
$ node script.js 2> error.log | tee info.log
在日常使用中,除非您>记录大量数据,否则不必担心阻塞/非阻塞二分法。
希望能帮助到你
Console.log在Windows中是异步的,而在linux / mac中是同步的。要使Windows中的console.log同步,可能在index.js文件的代码开头写入此行。该语句之后的任何console.log都将被解释器视为同步。
if (process.stdout._handle) process.stdout._handle.setBlocking(true);