等待用户在 Node.js 中输入输入

我理解 Node.js 中异步事件的基本原理,并正在学习如何以这种方式编写代码。然而,我陷入了以下情况:

我想编写代码,偶尔暂停用户输入。

该程序并不打算作为服务器(尽管目前它是用于命令行)。我知道这是 Node 的非典型用法。我的目标是最终将程序迁移回客户端 Javascript 应用程序,但是我发现在 Node.js 中工作对于调试来说既有趣又非常有用。这让我想起了我的例子,它说明了这个问题:

It reads in a text file and outputs each line unless the line ends with a "?". In that case, it should pause for user to clarify what was meant by that line. Currently my program outputs all lines first and waits for the clarifications at the end.

有没有什么方法可以强制 node.js 在命令行输入时暂停,以便在条件触发的情况下(即,该行以“ ?”结束)精确地输入命令行?

var fs = require("fs");
var filename = "";
var i = 0;
var lines = [];


// modeled on http://st-on-it.blogspot.com/2011/05/how-to-read-user-input-with-nodejs.html
var query = function(text, callback) {
process.stdin.resume();
process.stdout.write("Please clarify what was meant by: " + text);
process.stdin.once("data", function(data) {
callback(data.toString().trim());
});
};


if (process.argv.length > 2) {
filename = process.argv[2];
fs.readFile(filename, "ascii", function(err, data) {
if (err) {
console.error("" + err);
process.exit(1);
}
lines = data.split("\n");
for (i = 0; i < lines.length; i++) {
if (/\?$/.test(lines[i])) { // ask user for clarification
query(lines[i], function(response) {
console.log(response);
process.stdin.pause();
});
}
else {
console.log(lines[i]);
}
}
});
}
else {
console.error("File name must be supplied on command line.");
process.exit(1);
}
74182 次浏览

诀窍是不要迭代地执行,而是递归地执行 for 循环。因此,下一行是回调中的 printOut,它被称为 A: 在行被打印之后,或者 B: 在控制台输入被处理之后。

var fs = require("fs");


// modeled on http://st-on-it.blogspot.com/2011/05/how-to-read-user-input-with-nodejs.html
function query(text, callback) {
'use strict';
process.stdin.resume();
process.stdout.write("Please clarify what was meant by: " + text);
process.stdin.once("data", function (data) {
callback(data.toString().trim());
});
}


function printLinesWaitForQuestions(lines, someCallbackFunction) {
'use strict';


function continueProcessing() {
if (lines.length) {
printNextLine(lines.pop());
} else {
someCallbackFunction();
}
}


function printNextLine(line) {


if (/\?$/.test(line)) { // ask user for clarification
query(line, function (response) {
console.log(response);
process.stdin.pause();
continueProcessing();
});
} else {
console.log(line);
continueProcessing();
}
}


continueProcessing();
}


if (process.argv.length > 2) {
var filename = process.argv[2];
fs.readFile(filename, "ascii", function (err, data) {
'use strict';


if (err) {
console.error("" + err);
process.exit(1);
}


var lines = data.split("\n");
printLinesWaitForQuestions(lines, function () {
console.log('Were done now');
});
});
} else {
console.error("File name must be supplied on command line.");
process.exit(1);
}

这是一个很好的解决方案,原因有二:

  1. 它相对干净,整个过程可以包含在自己的闭包中,这可能导致模块化。

  2. 它不会破坏您可能希望执行的其他异步操作。

    不存在等待循环的迭代,并且每一行数组中只有一个异步任务被启动。如果在你的版本里,你有几百万条台词呢?你会瞬间输出数百万个异步输出... 糟糕!

    递归方法不仅允许更好地并发您想要执行的其他异步工作,而且您不会因为一个函数调用中的小型异步任务而阻塞事件循环。这可能导致内存问题、性能下降和其他值得避免的问题,特别是在大型输入上。

我找到了一个模块,可以很容易地对是或否进行处理:

Https://www.npmjs.com/package/cli-interact

安装: npm install cli-interact --save-dev

如何使用是直接从 npm 网站:

var query = require('cli-interact').getYesNo;
var answer = query('Is it true');
console.log('you answered:', answer);

这是另一种没有依赖关系的方法(读数线是内置的)

const readline = require('readline');


function askQuestion(query) {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});


return new Promise(resolve => rl.question(query, ans => {
rl.close();
resolve(ans);
}))
}




const ans = await askQuestion("Are you sure you want to deploy to PRODUCTION? ");

下面的答案与 mpen 相同,但没有令人困惑/不必要的承诺包装:

const readline = require('readline');
const rl = readline.createInterface({input: process.stdin, output: process.stdout});


rl.question('Press [Y] to continue: ', ans => {
if (ans == 'y') console.log('i will continue')
else console.log('i will not continue');
rl.close();
});