Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

命令行输入输出 #13

Open
luoway opened this issue Sep 17, 2023 · 0 comments
Open

命令行输入输出 #13

luoway opened this issue Sep 17, 2023 · 0 comments

Comments

@luoway
Copy link
Owner

luoway commented Sep 17, 2023

process.stdin

process.stdin 属性是 prcess 模块的内置API,用于监听用户输入。它返回一个可读流,通过 on() 注册事件监听器。

Node.js 为可读流提供了不同风格的API用法,以适应开发人员的习惯。

on('data')

收到数据触发回调,并等待下一次输入。

process.stdin.on('data', data => {
  console.log(`收到输入 ${data.toString()}`)
})

on('readable')

收到数据触发事件,需手动通过.read()读取数据。

process.stdin.on('readable', ()=>{
  // 使用循环,保持流不结束。

  // 卡死的写法
  while ( true ) {
    process.stdin.read()
  }
  // 能用的写法
  while ( process.stdin.read() ){ }
})

process.stdin.read() 返回Buffer类型数据,只有为空 null 时才会判断为假值。
这个表达式实现为同步用法,但背后是系统层面的IO操作,因此不同的语法结构会表现出明显差异。

上面的卡死写法与能用写法的区别,我理解为:

  • 卡死写法:每当 readable 事件回调执行时,开始无限循环地向IO操作队列中插入一次IO操作。
  • 能用写法:每当 readable 事件回调执行时,向IO操作队列中插入一次IO操作,等返回操作结果后开始下一次循环。

从这个例子可见,Node.js 将IO操作实现为同步语法后,配合代码循环语法是有坑的。

Node.js 官网也说 'readable' 事件较难理解,手动处理 'readable' 的意义是提升吞吐量,即提升性能。

In general, the readable.pipe() and 'data' event mechanisms are easier to understand than the 'readable' event. However, handling 'readable' might result in increased throughput.

pipe()

// 将输入流写入输出流
process.stdin.pipe( process.stdout )

pipe() 运行后返回传入的流,在传入的流是双工流(可读写)时,可实现链式调用。

process.stdout 、 process.stderr

process.stdout 返回一个可写流,用于打印输出信息,console.log()内部使用它打印输出;
process.stderr 返回一个可写流,用于打印错误信息,console.error()内部使用它打印错误。

两者都支持可写流的属性、方法。

常见用法:将子进程的输出、错误信息打印到控制台

const childProcess = require('child_process')

const cp = childProcess.exec(`node -e "console.log('child_process log');console.error('child_process error')"`)

cp.stdout.pipe(process.stdout)
cp.stderr.pipe(process.stderr)

Readline

Readline 是Node.js的内置模块,用于处理可读流类型的实际使用问题,代理基本的 process.stdin、process.stdout 操作,逐行读取。

createInterface

创建实例,配置选项。

const readline = require('node:readline')

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

实例创建后进程不会结束,而是持续处理用户输入,直到调用 rl.close() 结束。

prompt

提示字符串,在 Windows 中默认值是 >

  • rl.prompt():打印换行+提示字符串
  • rl.setPrompt():设置提示字符串内容
  • rl.getPrompt():获得提示字符串内容

使用提示字符串以便提示进程当前需要用户输入

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

rl.prompt() // 提示用户输入
rl.on('line', line=>{
    console.log('received:', line)
    rl.prompt() // 提示用户输入
})

静态方法

未创建实例也可以通过readline调用静态方法

  • moveCursor:相对当前光标位置,移动光标
  • cursorTo:移动光标到绝对位置
  • clearScreenDown:清除光标后的内容
  • clearLine:清除光标所在行及之后的内容

第三方库

  • prompts:轻量(依赖少)、交互友好的命令行提问
  • inquirer:功能丰富的命令行交互工具
  • chalk:为命令行输出添加样式,最多用户
  • kleur:为命令行输出添加样式,轻量,prompts依赖
  • figlet:在控制台打印由符号拼接成的图案字体
  • cli-progress:在控制台打印进度条

参考资料

@luoway luoway changed the title 打印输出 命令行输入输出 Sep 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant