【Node教程】- Node的readline (逐行读取)
readline
模块提供了一个接口,用于从可读流(如 process.stdin)读取数据,每次读取一行
先来看这个基本示例:
1.const readline = require('readline');
2.
3.const rl = readline.createInterface({
4. input: process.stdin,
5. output: process.stdout
6.});
7.
8.rl.question('你叫什么名字?', (answer) => {
9. // 对答案进行处理
10. console.log(`你好:${answer}`);
11.
12. rl.close();
13.});
在命令行中执行node hello.js
将出现如下结果:
1.$ node hello.js
2.你叫什么名字?liu
3.早上好,liu
通过这个示例,我们可以发现readline
模块可以方便的实现命令行的交互功能。实现如Node命令行工具开发【看段子】治疗的小应用
下面我们先来了解readline
的基本用法,然后再实现一个有趣的小功能。
readline基本用法
readline.Interface
类的实例是使用 readline.createInterface()
方法构造的。 每个实例都关联一个 input
可读流和一个 output
可写流。output
流用于为到达的用户输入打印提示,且从 input
流读取
创建Readline实例
1.readline.createInterface(options)
创建一个readline
的接口实例. 接受一个Object类型参数,可传递以下几个值:
input
- 要监听的可读流 (必需)output
- 要写入 readline 的可写流 (必须).completer
- 用于 Tab 自动补全的可选函数。(不常用)terminal
- 如果希望 input 和 output 流像 TTY 一样对待,那么传递参数 true ,并且经由 ANSI/VT100 转码。 默认情况下检查 isTTY 是否在 output 流上实例化。(不常用)
方法
rl.close()
关闭接口实例 (Interface instance), 放弃控制输入输出流。”close” 事件会被触发rl.pause()
暂停 readline 的输入流 (input stream), 如果有需要稍后还可以恢复。rl.prompt([preserveCursor])
为用户输入准备好readline,将现有的setPrompt选项放到新的一行,让用户有一个新的地方开始输入。将preserveCursor设为true来防止光标位置被重新设定成0。rl.question(query, callback)
预先提示指定的query,然后用户应答后触发指定的callback。 显示指定的query给用户后,当用户的应答被输入后,就触发了指定的callbackrl.resume()
恢复 readline 的输入流 (input stream).rl.setPrompt(prompt)
用于设置每当rl.prompt()
被调用时要被写入到output
的提示。rl.write(data[, key])
把data
或一个由key
指定的按键序列写入到output
事件
line
事件 :在 input 流接受了一个\n
时触发,通常在用户敲击回车或者返回时接收。 这是一个监听用户输入的利器。pause
事件: 输入流被暂停就会触发。 同样当输入流未被暂停,但收到 SIGCONT 也会触发。 (详见 SIGTSTP 和 SIGCONT 事件)resume
事件:只要输入流重新启用就会触发close
事件:当 close() 被调用时触发。 当 input流接收到end
事件时也会被触发. 流接收到表示结束传输的<ctrl>-D
,收到表示 SIGINT 的<ctrl>-C
,且 readline.Interface 实例上没有注册 SIGINT 事件监听器。
更多请参考node中文网
readline 实列
现在我们来实现一个命令行可交互的百度搜索
1.使用readline实现一个可交互的命令行
1.// 先来实现一个可交互命令行
2.const rl = readline.createInterface({
3. input: process.stdin,
4. output: process.stdout,
5. prompt: 'search>>> '
6.})
7.
8.rl.prompt()
9.
10.rl.on('line', (line) => {
11. console.log(line)
12. rl.prompt()
13.}).on('close', () => {
14. console.log('再见!')
15. process.exit(0)
16.})
node index.js
运行这段代码出现可交互的命令行,等待我们输入,输入完成回车后会打印出输入的值
2.使用http模块发起请求
这里为了加深对原生http模块的理解我们没用第三方模块,有很多好用的第三方模块如:request、superagent
1....
2.function search(words, callback) { // es6默认参数
3. let options = {
4. hostname: 'www.baidu.com',
5. port: 80,
6. path: `/s?wd=${encodeURI(words)}`,
7. method: 'GET'
8. }
9.
10. const req = http.request(options, (res) => {
11. // console.log(`STATUS: ${res.statusCode}`) //返回状态码
12. // console.log(`HEADERS: ${JSON.stringify(res.headers, null, 4)}`) // 返回头部
13. res.setEncoding('utf8') // 设置编码
14. let body = ''
15. res.on('data', (chunk) => { //监听 'data' 事件
16. body+=chunk
17. })
18. res.on('end', ()=>{
19. let $ = cheerio.load(body)
20. $('.t a').each(function(i, el){
21. console.log($(this).text(), $(this).attr('href'),'\n')
22. })
23. callback()
24. })
25. })
26. req.end() // end方法结束请求
27.}
28.
29....
这里我们用http模块发起客户端请求,并打印出来搜索结果的标题与链接,如果你忘记了http模块的使用可以回头查看了解并使用Http模块,http模块是node相当重要的模块,后续我们还将继续学习。
这里我们用到了cheerio具体使用可参考其官网
3. 实现命令行搜索
到此,我们只需将命令行的代码与http请求的代码整合起来就可以完成这个小项目了
1....
2.rl.on('line', (line) => {
3. search(line.trim(), ()=>{
4. rl.prompt()
5. })
6.}).on('close', () => {
7. console.log('再见!')
8. process.exit(0)
9.})
10....
现在在快命令行中试试我们一起完成的这个小案例吧!!!