Node.js CLI输入
在本教程中,我们将学习如何在Node.js CLI应用程序中获得用户输入。要做到这一点,你需要监听STDIN (标准输入),Node.js将其暴露为process.stdin ,一个可读流。
前提条件
-
你应该对JavaScript语言有一定的了解。
-
你应该在你的电脑上安装[Node.js]。
项目设置
为了开始工作,让我们来设置我们的项目。
创建一个名为node-cli-input 的新目录。
在该目录中,运行。
npm init -y
这将生成一个package.json 文件。
一旦完成,创建一个名为index.js 的新文件来编写我们的代码。
Readline包
readline 包是Node.js中的一个内置包。readline 是一个围绕标准I/O的包装器。
让我们把readline 包导入我们的index.js 文件中。
const readline = require('readline');
我们应该使用readline.createInterface() 方法创建一个新的readline 接口对象,并配置可读和可写流。让我们把输入和输出流分别设置为process.stdin 和process.stdout 。
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
我们可以使用rl.question() 方法向用户提出问题。
rl.question() 方法需要2个参数。
-
字符串:这个字符串将作为问题显示给用户。
-
回调函数:
rl.question()方法将等待,直到用户提供输入。一旦用户提供输入,这个回调函数将被执行。这个回调函数将得到用户的输入作为参数。
注意:我们应该使用回调函数里面的
rl.close()方法关闭流。如果不关闭,进程将一直处于空闲状态。
比如说
rl.question("Your favorite color? ", (input) => {
console.log(input);
rl.close();
});
输出。
Your favorite color? Black
Black
你可以使用rl.on() 方法为close streams 事件添加一个事件监听器。
rl.on('close', () => {
console.log('Streams Closed')
})
输出。
Your favorite color? Black
Black
Streams Closed
回调地狱
rl.question() 方法的问题是,它没有返回一个[Promise]。因此,我们不能使用[async/await]来暂停程序的流程,直到用户提供输入。
如果你想依次获得多个用户的输入,你必须在一个回调函数中进行,比如这样。
rl.question("Question 1? ", (answer1) => {
// do stuff
rl.question("Question 2? ", (answer2) => {
// do stuff
rl.question("Question 3? ", (answer3) => {
// do stuff
rl.question("Question 4? ", (answer4) => {
console.log(answer1, answer2, answer3, answer4);
rl.close();
});
});
});
});
正如你所看到的,这很快就会失去控制,代码将很难管理。
异步迭代器
异步迭代允许我们对异步来的数据进行迭代,按需进行。你可以创建一个异步迭代器,对输入流中的每一行进行迭代。
for await (const line of rl) {
// Each line in from the input stream will be available successively here as `line`.
}
我们不能在async 函数之外使用await 关键字。因此,我们需要把所有的代码包在一个异步函数里面。
async function main() {
// do your stuff here
for await (const line of rl) {
// Each line in from the input stream will be available here as `line`.
}
}
main();
让我们创建一个名为input() 的新函数来提示用户并获得输入。
我们可以使用readline 对象的Symbol.asyncIterator来获取输入流中的下一个值。
async function input(prompt) {
console.log(prompt);
return (await rl[Symbol.asyncIterator]().next()).value;
}
现在,我们可以使用这个函数从输入流中获取数值,并使用await 关键字来暂停执行,直到我们得到用户的输入。
async function main() {
const name = await input("May I have your name? ");
const color = await input("Your favorite color? ");
console.log(name, color);
rl.close();
}
main();
Readline同步包
如果你不介意安装一个外部包,这将增加你正在构建的CLI应用程序的包的大小,你可以使用readline-sync 包来以同步的方式获得用户的输入。
让我们通过运行来安装readline-sync 。
npm install readline-sync
现在,让我们导入该包。
const readlineSync = require("readline-sync");
与readline 包类似,你可以使用readlineSync.question() 方法来提示用户输入。
与readline 包不同的是,你不需要给这个函数传递一个回调函数。readlineSync.question() 方法将返回用户的输入。
let input = readlineSync.question('May I have your name? ');
console.log(`Hi ${input}!`);
readlineSync 包也有其他函数,如readlineSync.keyInYN(),readlineSync.keyInSelect(), 等。
readlineSync.keyInYN() 是用来获取用户在不按回车键的情况下对单个按键的响应。如果按了**"Y"**,该函数将返回true ,如果按了其他东西,则返回false 。
if (readlineSync.keyInYN('Yes?')) {
// 'Y' key was pressed.
} else {
// Another key was pressed.
}
readlineSync.keyInSelect() 用来提示用户从一个列表中选择一个项目。该函数将返回用户选择的数字。当我们使用这个函数时,用户不需要按回车键。
let colors = ['Black', 'White', 'Gray', 'Yellow', 'Blue'];
let index = readlineSync.keyInSelect(colors, 'Favorite Color?');
console.log(colors[index]);
输出。
[1] Black
[2] White
[3] Gray
[4] Yellow
[5] Blue
[0] CANCEL
Favorite Color? [1...5 / 0]: 2
White
让我们回顾一下
-
我们使用
readline包来提示用户的输入。 -
我们为readline流的
close事件添加了一个事件监听器。 -
我们使用异步迭代器来编写一个异步函数来获取用户的输入,以防止回调地狱。
-
我们使用
readline-sync包来同步提示用户的输入。
恭喜你,🥳你成功了。