一个打印3行输出的非常简单的程序:
console.log('a');
console.log('b');
console.log('c');
程序是否有一种方法可以删除打印后的最后一行?,即
console.log('a');
console.log('b');
console.log('c');
eraseLastLine();
console.log('C');
会产生:
a
b
C
答案 0 :(得分:15)
简单的解决方案是不打印换行符(即不要使用console.log
)。
process.stdout.write
打印不带EOL字符的行。\r
)字符返回到行的开头。\e[K
清除光标位置到行尾的所有字符。示例:
process.stdout.write("000");
process.stdout.write("\n111");
process.stdout.write("\n222");
对于这一行,输出将是:
000
111
222
但是,如果执行:
process.stdout.write("000");
process.stdout.write("\n111");
process.stdout.write("\n222");
process.stdout.write("\r\x1b[K")
process.stdout.write("333");
输出结果为:
000
111
222\r\x1b[K
333
但是,终端将显示:
000
111
333
答案 1 :(得分:5)
方式一:
const clearLastLine = () => {
process.stdout.moveCursor(0, -1) // up one line
process.stdout.clearLine(1) // from cursor to end
}
方式 2:
const readline = require('readline')
const clearLastLine = () => {
readline.moveCursor(process.stdout, 0, -1) // up one line
readline.clearLine(process.stdout, 1) // from cursor to end
}
方式 3:
const ESC = '\x1b' // ASCII escape character
const CSI = ESC + '[' // control sequence introducer
const clearLastLine = () => {
process.stdout.write(CSI + 'A') // moves cursor up one line
process.stdout.write(CSI + 'K') // clears from cursor to line end
}
方式 1 使用内置 tty
模块提供的方法。
方式 2 使用内置的 readline
模块。
方式 3 使用 ANSI escape sequences。
我通过查看 ANSI escape sequences 的源代码了解了 log-update,这是我从 dthree 的 answer 中了解到的。在做了更多研究之后,我了解了内置的 readline
和 tty
模块。
通过阅读Node.js的源代码,我了解到方式1中使用的方法本质上是对方式2中使用的方法的包装,而方式2中使用的方法本质上是对中使用的方法的包装方式 3. 所以每一种方式最终都会在引擎盖下做基本相同的事情。上级到下级的方式我已经排序了。
我建议使用方式 1 替代方式 2 和方式 2 替代方式 3,主要是因为我认为方式 1 比方式 2 代码更少且更清晰(因此更具可读性),而方式 2 代码更少且更清晰(因此比方法 3 更具可读性,并且通过使用较低级别的方法实现的性能改进(如果有)可能可以忽略不计。但是,我认为方法 3 避免加载内置的 readline
模块。
这个解决方案(每一种方式)都假设您的光标位于程序调用 clearLastLine()
之前的空行的开头。正如 Gajus 中的 his answer 所述,如果您的光标位于最后一行的末尾,则解决方案会更简单。那么您可以使用 process.stdout.write()
(而不是 console.log()
)来打印没有尾随换行符的最后一行吗?
或者,如果您不需要首先打印最后一行,则解决方案甚至更简单。所有这些都是在修改标准输出 code smell 吗?你能重新设计你的代码,这样最后一行就不会被打印出来吗?
就我而言,我正在测试我编写的调用 console.error()
的辅助函数,并且我不希望记录的错误消息显示在我的测试输出中。因此,与其让我的辅助函数调用 console.error()
,我还可以让它抛出错误(或者只返回错误代码和/或消息或布尔值)。然后,如果我的辅助函数抛出错误(或返回错误代码和/或消息或 false
),则调用我的辅助函数的主程序可能会调用 console.error()
。或者我可以将一个布尔值 flag argument 传递给我的辅助函数,告诉它是否记录错误。或者我可以重定向 stderr,或 mock 全局 console
或 stub console.error()
等
如果您想清除写入 system.stdout
的最后三行,您可以这样做:
const clearLastLines = (count) => {
process.stdout.moveCursor(0, -count)
process.stdout.clearScreenDown()
}
clearLastLines(3)
答案 2 :(得分:4)
以下适用于我:
process.stdout.clearLine();
process.stdout.cursorTo(0);
答案 3 :(得分:2)
答案 4 :(得分:0)
有一个简单的解决方法:
process.stdout.write(`\x1Bc\rData left: ${currentPercentage}%`)
那将打印出类似以下内容: “剩余数据:100%” ...,然后使用它,您将在每次迭代后清除屏幕。
'\ x1Bc'清除行,并且'\ r'返回第0列。
答案 5 :(得分:0)
唯一对我有用的模块是single-line-log
安装:
npm i single-line-log
导入:
var log = require('single-line-log').stdout;
然后不用console.log()
记录进度条,而是使用log()
:
// OLD:
while (task_is_running) {
console.log(Progress.update())
}
// NEW:
while (task_is_running) {
log(Progress.update())
}
结合 clui
作为进度条,效果很好。