如果在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
包内的异步操作也应该发生同样的事情。因此,留下可见的终端窗口对正在运行的服务器是危险的。
如何更改代码以避免此类行为?
答案 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的说明。
警告:同步写入会阻止事件循环,直到写入完成。在输出到文件的情况下,这可能接近瞬时,但是在高系统负载,未在接收端读取的管道,或者使用慢速终端或文件系统,可能经常阻止事件循环并且长到足以产生严重的负面性能影响。
似乎可以使用您已经提出的方法构建部分解决方案:
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, ()=>{})
}