node.js 以交互方式从控制台读取值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8128578/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Reading value from console, interactively
提问by Risto Novik
I thought to make an simple server http server with some console extension. I found the snippet to read from command line data.
我想用一些控制台扩展来制作一个简单的服务器 http 服务器。我找到了从命令行数据中读取的片段。
var i = rl.createInterface(process.stdin, process.stdout, null);
i.question('Write your name: ', function(answer) {
console.log('Nice to meet you> ' + answer);
i.close();
process.stdin.destroy();
});
well to ask the questions repeatedly, i cant simply use the while(done) { }loop? Also well if the server receives output at the question time, it ruins the line.
好反复问这些问题,我不能简单地使用while(done) { }循环?同样,如果服务器在提问时间收到输出,它会破坏线路。
回答by rob
you can't do a "while(done)" loop because that would require blocking on input, something node.js doesn't like to do.
你不能做一个“while(done)”循环,因为这需要阻塞输入,这是 node.js 不喜欢做的。
Instead set up a callback to be called each time something is entered:
而是设置每次输入内容时调用的回调:
var stdin = process.openStdin();
stdin.addListener("data", function(d) {
// note: d is an object, and when converted to a string it will
// end with a linefeed. so we (rather crudely) account for that
// with toString() and then trim()
console.log("you entered: [" +
d.toString().trim() + "]");
});
回答by Madhan Ganesh
I've used another API for this purpose..
为此,我使用了另一个 API。
var readline = require('readline');
var rl = readline.createInterface(process.stdin, process.stdout);
rl.setPrompt('guess> ');
rl.prompt();
rl.on('line', function(line) {
if (line === "right") rl.close();
rl.prompt();
}).on('close',function(){
process.exit(0);
});
This allows to prompt in loop until the answer is right. Also it gives nice little console.You can find the details @ http://nodejs.org/api/readline.html#readline_example_tiny_cli
这允许循环提示,直到答案是right。它还提供了漂亮的小控制台。您可以找到详细信息@ http://nodejs.org/api/readline.html#readline_example_tiny_cli
回答by Patrick.SE
The Readline API has changed quite a bit since 12'. The doc's show a useful example to capture user input from a standard stream :
自 12 年以来,Readline API 发生了很大变化。该文档显示了一个从标准流中捕获用户输入的有用示例:
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question('What do you think of Node.js? ', (answer) => {
console.log('Thank you for your valuable feedback:', answer);
rl.close();
});
回答by Arango
Please use readline-sync, this lets you working with synchronous console withouts callbacks hells. Even works with passwords:
请使用readline-sync,这使您可以使用同步控制台而无需回调地狱。甚至可以使用密码:
var favFood = read.question('What is your favorite food? ', {
hideEchoBack: true // The typed text on screen is hidden by `*` (default).
});
回答by Wiktor Zychla
I believe this deserves a modern async-awaitanswer, assuming node >= 7.x is used.
我相信这值得一个现代的async-await答案,假设使用 node >= 7.x。
The answer still uses ReadLine::questionbut wraps it so that the while (done) {}is possible, which is something the OP asks about explicitely.
答案仍然使用ReadLine::question但将其包装起来,以便while (done) {}可能,这是 OP 明确询问的内容。
var cl = readln.createInterface( process.stdin, process.stdout );
var question = function(q) {
return new Promise( (res, rej) => {
cl.question( q, answer => {
res(answer);
})
});
};
and then an example usage
然后是一个示例用法
(async function main() {
var answer;
while ( answer != 'yes' ) {
answer = await question('Are you sure? ');
}
console.log( 'finally you are sure!');
})();
leads to following conversation
导致以下对话
Are you sure? no
Are you sure? no
Are you sure? yes
finally you are sure!
回答by zurfyx
@rob answer will work most of the times, but it might not work as you expect with long inputs.
@rob 答案在大多数情况下都可以使用,但是对于长输入,它可能无法像您期望的那样工作。
That is what you should be using instead:
这就是你应该使用的:
const stdin = process.openStdin();
let content = '';
stdin.addListener('data', d => {
content += d.toString();
});
stdin.addListener('end', () => {
console.info(`Input: ${content}`);
});
Explanation on why this solution works:
关于此解决方案为何有效的说明:
addListener('data')works like a buffer, callback will be called when it is full or/and its the end of input.
addListener('data')像缓冲区一样工作,当它已满或/和输入结束时将调用回调。
What about long inputs? A single 'data'callback will not be enough, hence it you will get your input split in two or more parts. That is often not convenient.
长输入呢?单个'data'回调是不够的,因此您会将输入分成两部分或更多部分。这通常不方便。
addListener('end')will notify us when the stdin reader is done reading our input. Since we have been storing the previous data, we can now read and process it all together.
addListener('end')当标准输入读取器完成读取我们的输入时会通知我们。由于我们已经存储了之前的数据,我们现在可以一起读取和处理它们。
回答by Diogo Cardoso
I recommend using Inquirer, since it provides a collection of common interactive command line user interfaces.
我建议使用Inquirer,因为它提供了一组常见的交互式命令行用户界面。
const inquirer = require('inquirer');
const questions = [{
type: 'input',
name: 'name',
message: "What's your name?",
}];
const answers = await inquirer.prompt(questions);
console.log(answers);
回答by Miguel Mota
Here's a example:
下面是一个例子:
const stdin = process.openStdin()
process.stdout.write('Enter name: ')
stdin.addListener('data', text => {
const name = text.toString().trim()
console.log('Your name is: ' + name)
stdin.pause() // stop reading
})
Output:
输出:
Enter name: bob
Your name is: bob
回答by Ragnarok Ragdoll
This is overcomplicated. An easier version of:
这太复杂了。一个更简单的版本:
var rl = require('readline');
rl.createInterface... etc
would be to use
将使用
var rl = require('readline-sync');
then it will wait when you use
然后它会在你使用时等待
rl.question('string');
then it is easier to repeat. for example:
然后更容易重复。例如:
var rl = require('readline-sync');
for(let i=0;i<10;i++) {
var ans = rl.question('What\'s your favourite food?');
console.log('I like '+ans+' too!');
}
回答by Stefan Musarra
I had to write a "tic-tac-toe" game in Node that took input from the command line, and wrote this basic async/await block of code that did the trick.
我不得不在 Node 中编写一个“井字棋”游戏,它从命令行获取输入,并编写了这个基本的异步/等待代码块来实现这一点。
const readline = require('readline')
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
async function getAnswer (prompt) {
const answer = await new Promise((resolve, reject) =>{
rl.question(`${prompt}\n`, (answer) => {
resolve(answer)
});
})
return answer
}
let done = false
const playGame = async () => {
let i = 1
let prompt = `Question #${i}, enter "q" to quit`
while (!done) {
i += 1
const answer = await getAnswer(prompt)
console.log(`${answer}`)
prompt = processAnswer(answer, i)
}
rl.close()
}
const processAnswer = (answer, i) => {
// this will be set depending on the answer
let prompt = `Question #${i}, enter "q" to quit`
// if answer === 'q', then quit
if (answer === 'q') {
console.log('User entered q to quit')
done = true
return
}
// parse answer
// if answer is invalid, return new prompt to reenter
// if answer is valid, process next move
// create next prompt
return prompt
}
playGame()

