Node.js 在控制台中显示每行更新的NodeJS脚本

Node.js 在控制台中显示每行更新的NodeJS脚本,node.js,command-line-interface,Node.js,Command Line Interface,我有一个用NodeJS编写的小命令行程序来处理给定目录中的所有文本文件。由于节点是异步的,脚本将读取所有文件,处理它们并输出如下内容 Converting file: example-file-1.txt Converting file: example-file-2.txt Converting file: example-file-3.txt Converting file: example-file-4.txt File example-file-3.txt converted! File

我有一个用NodeJS编写的小命令行程序来处理给定目录中的所有文本文件。由于节点是异步的,脚本将读取所有文件,处理它们并输出如下内容

Converting file: example-file-1.txt
Converting file: example-file-2.txt
Converting file: example-file-3.txt
Converting file: example-file-4.txt
File example-file-3.txt converted!
File example-file-1.txt converted!
File example-file-2.txt converted!
File example-file-4.txt converted!
File example-file-1.txt: DONE! // processing of this file has finished
File example-file-2.txt: converting... // this file is still processing
File example-file-3.txt: DONE!
File example-file-4.txt: converting...
这不是很漂亮,因为文件大小不同,处理速度不同,“转换”的消息也不整齐。
我想看到的是这样的东西

Converting file: example-file-1.txt
Converting file: example-file-2.txt
Converting file: example-file-3.txt
Converting file: example-file-4.txt
File example-file-3.txt converted!
File example-file-1.txt converted!
File example-file-2.txt converted!
File example-file-4.txt converted!
File example-file-1.txt: DONE! // processing of this file has finished
File example-file-2.txt: converting... // this file is still processing
File example-file-3.txt: DONE!
File example-file-4.txt: converting...
每行最右边的部分应随进度动态更新

这里我真正想问的是如何在控制台中显示几行消息,我可以随着脚本的进行而更新这些消息。

使用标准终端功能,只有回车符
\r
允许将光标重置到当前行的开头,并覆盖光标进行更新

大多数终端支持ANSI/VT100控制代码,允许设置颜色、光标定位和其他屏幕更新。使用这些功能的节点模块例如:

  • :使用ansi终端字符写入颜色和光标位置
  • :一个类似诅咒的库,具有node.js的高级终端接口API
Windows支持转义序列

最小示例 下面的示例通过直接发送控制命令并写出缓存的屏幕来解决该任务。使用的命令有:

  • 通过发送
    \x1b[H
    并在左上角重新定位光标
  • 通过发送
    \x1b[2J
    清除屏幕
  • 写入的行数超过可用行数将导致闪烁

    var进度={
    'example-file-1.txt':'converting',
    'example-file-2.txt':'converting',
    “example-file-3.txt”:“正在转换”
    }
    函数renderProgress(){
    //重置光标,清除屏幕,不写新行
    process.stdout.write('\x1b[H\x1b[2J')
    //取得进展
    Object.keys(progress.forEach(filename=>console.log(`${filename}:${progress[filename]}'))
    }
    函数updateProgress(文件名、状态){
    进度[文件名]=状态
    renderProgress()
    }
    //取得初步进展
    renderProgress()
    //simulare更新
    setTimeout(()=>updateProgress('example-file-2.txt','done'),1000)
    setTimeout(()=>updateProgress('example-file-1.txt','referencing'),2500)
    setTimeout(()=>updateProgress('example-file-3.txt','done'),4000)
    setTimeout(()=>updateProgress('example-file-1.txt','done'),6000)
    
    我最终通过回调中的一个简单递归函数以同步方式处理所有文件。用户库在终端窗口中显示每个文件的进度

    var files = [];
    
    // get all "txt" files from a given directory and store them in an array "files"
    function getFiles(dir) {
        var filesRaw = fs.readdirSync(dir);
        for (var i in filesRaw) {
            var name = dir === '.' ? filesRaw[i] : dir + '/' + filesRaw[i];
            var ext = path.extname(name);
            if (!fs.statSync(name).isDirectory()) {
                if (ext == '.txt') {
                    files.push(path.resolve(process.cwd(), name));
                }
            }
        }
        // only after the directory is read, run the function that starts processing those files
        recode(files);
    }
    
    function recode() {
        if (files.length > 0) {
            var fileName = files.shift();
            // this is the terminal spinner library
            const spinner = ora(`File ${path.basename(fileName)} processing...`).start();
            var fileSingle = fs.readFileSync(fileName);
            var data = new Buffer(fileSingle, "ascii");
            var translated = encoding.convert(data, "UTF-8", "CP1250");
            var converted = iconvlite.encode(translated, "utf8").toString();
    
            fs.writeFile(fileName, converted, function(err) {
                if (err) {
                    spinner.fail(`File ${path.basename(fileName)} failed.`);
                    console.log(err);
                } else {
                    spinner.succeed(`File ${path.basename(fileName)} DONE!`);
                }
                // process another file from the files array only when the previous file is finished and saved to disk
                recode(files);
            });
        } else {
            console.log('No more files to process or all files done.');
        }
    }
    

    谢谢@Robert,但我最终重新思考了我的应用程序流程,请参见下面的回复。