当滚动控制台窗口时,Node.js停止

时间:2018-01-02 22:34:53

标签: node.js windows performance event-loop

如果在Windows(至少8)下的Node.js中运行以下脚本

const init = +new Date;
setInterval(() => {
    console.log(+new Date - init);
}, 1000);

并拖动控制台窗口滚动条的拇指,脚本的输出类似于

1001
2003  // long drag here
12368 // its result
13370
14372

看起来Node.js的事件循环在滚动期间停止。 http包内的异步操作也应该发生同样的事情。因此,留下可见的终端窗口对正在运行的服务器是危险的。

如何更改代码以避免此类行为?

4 个答案:

答案 0 :(得分:6)

滚动或选择文本时,NodeJS不会暂停。将数据发送到stdout的唯一函数将暂停。 在您的服务器中,您可以将日志数据发送到文件,这样服务器就不会停止。

例如,请参阅此代码:

const init = +new Date;
var str=''
setInterval(() => {
    x=(+new Date - init).toString();;
    str+=x + '\n'
}, 1000);

setTimeout(function(){
    console.log(str)
},5000)

我在前5秒内选择了文字,结果就是这样:

C:\me>node a
1002
2002
3002
4003

您可以看到没有'暂停'

如您所见,第一个事件循环setInterval并未停止,因为内部没有console.log

现在,当您使用输出文件进行日志记录时,可以使用tail -f查看实时日志。这将显示输出文件中的每一个新行。

答案 1 :(得分:4)

当您在控制台中滚动或点击时,您的控制台实际上是暂停的,因为它进入了选择模式。看看标题栏,因为它暂停了它可能会说选择。

要防止出现此问题,请编辑命令提示符的属性,然后取消选择"快速编辑模式"。

答案 2 :(得分:2)

节点文档中有两条信息可能会为这种行为提供一些线索:

摘自Console

  

警告:全局控制台对象的方法既不像它们类似的浏览器API一致同步,也不像所有其他Node.js流一样异步。有关更多信息,请参阅有关进程I / O的说明。

摘自A note on process I/O

  

警告:同步写入会阻止事件循环,直到写入完成。在输出到文件的情况下,这可能接近瞬时,但是在高系统负载,未在接收端读取的管道,或者使用慢速终端或文件系统,可能经常阻止事件循环并且长到足以产生严重的负面性能影响。

似乎可以使用您已经提出的方法构建部分解决方案:

const fs = require('fs');
const init = +new Date;
setInterval(() => {
    fs.write(1,String(+new Date - init)+'\n',null,'utf8',()=>{});
}, 1000);

如果您开始选择,它仍会阻止用户界面,但不会停止处理:

2296
3300  // long pause here when selection was started
4313  // all those lines printed at the same time after selection was aborted
5315
6316
7326
8331
9336
10346
11356
12366
13372

答案 3 :(得分:0)

如果要使console.log和console.error在所有平台上始终异步,则可以通过将fs.write设置为fd 1(stdout)或fd 2(stderr)来实现。

const fs = require('fs')
const util = require('util')

// used by console.log
process.stdout.write = function write (str) {
  fs.write(1, str, ()=>{})
}

// used by console.error
process.stderr.write = function write (str) {
  fs.write(2, str, ()=>{})
}