Node.js 在滚动控制台 window 时停止
Node.js halts when console window is scrolled
如果你运行下面的脚本在Node.js下Windows(至少8个)
const init = +new Date;
setInterval(() => {
console.log(+new Date - init);
}, 1000);
并拖动控制台滚动条的滑块 window,脚本的输出类似于
1001
2003 // long drag here
12368 // its result
13370
14372
看起来 Node.js' 事件循环在滚动期间停止。 http
包内的异步操作也应该发生同样的事情。因此,留下可见终端 window 对 运行ning 服务器是危险的。
如何更改代码以避免此类行为?
当您在控制台中滚动或单击时,您的控制台实际上正在暂停,因为它正在进入 select 模式。看看标题栏,因为它暂停了,它可能会说 select.
要防止这种行为,请编辑命令提示符的属性,然后取消select "quick edit mode".
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
可以看到没有'pause'.
如您所见,第一个事件循环 setInterval
没有停止,因为里面没有 console.log
。
现在,当您使用输出文件进行日志记录时,您可以使用 tail -f
查看实时日志。这将显示输出文件中的每一行。
节点文档中有两条信息可以为该行为的原因提供一些线索:
摘自Console:
Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.
Warning: Synchronous writes block the event loop until the write has completed. This can be near instantaneous in the case of output to a file, but under high system load, pipes that are not being read at the receiving end, or with slow terminals or file systems, its possible for the event loop to be blocked often enough and long enough to have severe negative performance impacts.
而且似乎可以使用您已经提出的方法构建部分解决方案:
const fs = require('fs');
const init = +new Date;
setInterval(() => {
fs.write(1,String(+new Date - init)+'\n',null,'utf8',()=>{});
}, 1000);
如果您开始选择,它仍然会阻塞 UI,但不会停止处理:
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
如果你想让你的 console.log 和 console.error 在所有平台上总是异步的,你可以通过使用 fs.write
到 fd 1 (stdout) 或 fd 2 来实现(标准错误).
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, ()=>{})
}
如果你运行下面的脚本在Node.js下Windows(至少8个)
const init = +new Date;
setInterval(() => {
console.log(+new Date - init);
}, 1000);
并拖动控制台滚动条的滑块 window,脚本的输出类似于
1001
2003 // long drag here
12368 // its result
13370
14372
看起来 Node.js' 事件循环在滚动期间停止。 http
包内的异步操作也应该发生同样的事情。因此,留下可见终端 window 对 运行ning 服务器是危险的。
如何更改代码以避免此类行为?
当您在控制台中滚动或单击时,您的控制台实际上正在暂停,因为它正在进入 select 模式。看看标题栏,因为它暂停了,它可能会说 select.
要防止这种行为,请编辑命令提示符的属性,然后取消select "quick edit mode".
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
可以看到没有'pause'.
如您所见,第一个事件循环 setInterval
没有停止,因为里面没有 console.log
。
现在,当您使用输出文件进行日志记录时,您可以使用 tail -f
查看实时日志。这将显示输出文件中的每一行。
节点文档中有两条信息可以为该行为的原因提供一些线索:
摘自Console:
Warning: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.
Warning: Synchronous writes block the event loop until the write has completed. This can be near instantaneous in the case of output to a file, but under high system load, pipes that are not being read at the receiving end, or with slow terminals or file systems, its possible for the event loop to be blocked often enough and long enough to have severe negative performance impacts.
而且似乎可以使用您已经提出的方法构建部分解决方案:
const fs = require('fs');
const init = +new Date;
setInterval(() => {
fs.write(1,String(+new Date - init)+'\n',null,'utf8',()=>{});
}, 1000);
如果您开始选择,它仍然会阻塞 UI,但不会停止处理:
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
如果你想让你的 console.log 和 console.error 在所有平台上总是异步的,你可以通过使用 fs.write
到 fd 1 (stdout) 或 fd 2 来实现(标准错误).
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, ()=>{})
}