使用Node REPL控制台时,我正在寻找一种异步调用的方法,既不会锁定控制台输入,也不会在返回时破坏控制台提示符。
我在REPL中看到了一些处理异步调用的解决方案,在这里编写自己的自定义eval
函数,你可以检查执行代码的结果,看看它是否是一个promise / async对象,只是在结算之前不会返回。
但是,我想解决重复后台进程记录其进度的问题。理想情况下,我希望它的行为类似于Chrome Javascript控制台,如果您在控制台提示符上部分打印了一个命令,并且记录了异步结果,那么您输入的行将被移动一行,并且日志插在它上面。
所以,在功能上,我想插入一个逻辑,当调用console.log()
时,首先清除包含游标的行,然后写入log()
的内容,然后是REPL提示(以及用户到目前为止输入的内容)将在新输出后的行上重写。
有没有办法挂钩到REPL对象来实现这个目的?这是对REPL输出流的一些高级操作(即只能在支持“擦除到行首”转义码的终端上进行)?
答案 0 :(得分:1)
直接进入输出流我设法得到了一些像我想要的东西:
var server = repl.start({
prompt: '> '
});
server.context.console.log = function(msg) {
var rli = server.rli;
server.outputStream.write('\033[2K\033[1G'); // Erase to beginning of line, and reposition cursor at beginning of line
server.outputStream.write(msg+"\n");
server.outputStream.write(''+rli._prompt+rli.line); // Redraw existing line
server.outputStream.write('\033['+(rli.cursor+rli._promptLength+1)+'G'); // Move the cursor to where it was
}
server.context.doTimeout = function() {
setTimeout(function() {
server.context.console.log('Timeout done!');
}, 2000);
};
尽管所有这些都假定符合ANSI标准的输出流是输出,并且感觉很糟糕,所以会覆盖console.log()
函数。是否有更合规的方法来处理这个问题,或者这是最好的方法吗?
答案 1 :(得分:1)
仍然,现在我无法在 StackOverflow 上找到满意的现代答案。 在互联网上花了几个小时后,我为最新的 Node (v15.*) 想出了这个解决方案
const log = (msg) => {
rl.output.write('\r')
rl.output.write(msg + '\n')
rl.displayPrompt(true)
}
基本上,清除行,写入日志,然后再次显示提示。非常适合我的情况。
改进的解决方案。 如果缓冲行不长于日志,则上述方法效果很好。所以这是另一个版本,用空格字符填充日志的其余部分
const log = (msg) => {
rl.output.write('\r');
rl.output.write(_.padEnd(msg, process.stdout.columns - 2, ' ') + '\n');
rl.displayPrompt(true);
};
答案 2 :(得分:0)
基于@MidnightLightning的较早答案。
从节点v12.15.0之前的某个时候开始,console.log覆盖看起来像:
activeRepl.context.console.log = (msg) => {
const promptOffset = Server._prompt.length + Server.line.length;
Server.outputStream.write('\033[2K\033[1G'); // Erase to beginning of line, and reposition cursor at beginning of line
Server.outputStream.write(msg + "\n");
Server.outputStream.write('' + Server._prompt + Server.line); // Redraw existing line
Server.outputStream.write('\033[' + (promptOffset + 1) + 'G'); // Move the cursor to where it was
};