我正在 ts 中创建一个 CLI 程序,我的命令将进度写入控制台。我想通过避免编写这样的几行来使其更漂亮:
Starting microservice api-gateway 🔄
Microservice api-gateway started ✅
Starting microservice Agenda 🔄
Microservice Agenda started ✅
Starting microservice Device 🔄
Microservice Device started ✅
...
只需重写第一行即可修改表情符号:
Starting microservice api-gateway 🔄 -> Starting microservice api-gateway ✅
Starting microservice Agenda 🔄 -> Starting microservice Agenda ✅
Starting microservice Device 🔄 -> Starting microservice Device ✅
...
我成功实现了第一个版本:
process.stdout.write("Starting microservice api-gateway 🔄")
# make something
process.stdout.moveCursor(0,-1)
process.stdout.write("✅")
这段代码工作完美,但有一个问题:两个函数之间不应该向控制台写入任何其他内容。
所以我设法实现了第二个版本来处理这个问题。此版本使用全局变量来存储打印到表中的每个日志:
writeLog.ts
/**
* Writes a log to the console and returns the index of the log
* @param log The log to write
* @return {number} The index of the log
*/
export default function writeLog(log: string): number {
process.stdout.write(log);
let newLog: Log = {
log: log,
cursorPos: {
x: process.stdout.rows,
y: process.stdout.columns
}
};
let index = global.logs.push(newLog);
process.stdout.write("\n");
return index - 1;
}
重写Log.ts
/**
* rewrite a log in the console
* @param index The index of the log
* @param log The new log
*/
export default function rewriteLog(index: number, log: string) {
let row = global.logs.length - index;
let col = global.logs[index].cursorPos.y;
let pos = {
row: process.stdout.rows,
col: process.stdout.columns
}
process.stdout.moveCursor(-col, -row);
process.stdout.clearLine(1);
process.stdout.write(log + "\n");
process.stdout.moveCursor(
pos.col - col,
pos.row - row
);
global.logs[index].log = log;
}
这两个函数可以让我写日志并重写它。它可以正常工作,除了两种情况:如果它们被异步调用,或者它们被调用得太快。
对于太快的调用,我的研究引导我找到
process.stdout.write()
和 process.stdout.moveCursor()
函数,它们包含一个回调参数,这意味着该函数不是同步的,因此我有可能在第一个函数完成写入甚至开始之前再次移动光标。
对于第二个问题,它几乎是相同的,只有一个游标,我希望它同时出现在多个地方,为了克服这个问题,我考虑是否可以确保一个函数同时只能被一个进程使用并暂停其他所有内容,这打破了异步原则,但我基于例如cpp中互斥体的原则。不幸的是我找不到任何相关信息。