这篇是延续以下文章的内容
第四篇 - 进程、行程、过程、行程、程序、处理程序、Process
第五篇 - Task queue、EventLoop
第六篇 - Node's EventLoop和Node程式执行顺序
第七篇 - 第一次用EventEmiter就用来做坏坏的事ヽ(́◕◞౪◟◕‵)ノ
如果还没看过以上内容的可自行斟酌观看。
上次只提到可以透过 process 物件查看 Node 环境等资讯,
这篇主要会讲 process 的 I/O(标準输出入)。
但我觉得其实不影响此篇独立观看~只是顺边帮以前的文章打一点广告
此篇学习目标 ◑ω◐ :
Process标準串流是什么利用 stdin 读取串流利用 stdout 与 stderr 分别处理串流输出实际使用!建立简单的 CLI 来查询鼠年马拉松的文章登记情况Process标準串流是什么
process 的 I/O 函式其实是继承自 EventEmitter,这代表说我们可以发出事件或是监听事件撷取任何资料来做处理,而且这些串流是无敌的!你没办法把它关闭或是在应用程式中删除掉。
听起来是不是特别的令人兴奋啊!
而串流在 Node 中主要分别由 stdin(标準输入)、 stdout (标準输出) 、 stderr (标準错误) 所组成。
而 process 会以三种函式来使用
这边你应该会想说...
咦(((゚д゚)))!
怎么 stdout 和 stderr 都是写入串流,感觉是不是一样的啊?
其实他是刻意这样分的,多建构一个 stderr 是为了想要分别处理预期的输出与发生问题的输出,我相信你不会想要特地在同一个地方还要自行判断和分类的对吧!
我相信正在读的你已经迫不急待想做一些嘿咻脸的事了 ⁽⁽٩(๑˃̶͈̀ ᗨ ˂̶͈́)۶⁾⁾
利用 stdin 读取串流
首先必须设定串流的编码...
process.stdin.setEncoding('utf-8');
不然会发生很可怕的事...
就是... 看不懂 xDDD
如果没有设定只是结果会输出 buffer 而不是字串而已啦 (´⊙ω⊙`)
至于 buffer 是什么有兴趣可以自行研究,之后"应该"有机会我也会分享,因为我现在不想误导各位。
接下来我们监听 readable
事件,这个事件主要是会让我们知道有资料可以读取的事件,然后再藉由 process.stdin.read()
读取串流
process.stdin.setEncoding('utf-8');process.stdin.on('readable', () => { const input = process.stdin.read(); if (input !== null) { console.log(`我监听到东西啦 -> ${input}`) }});
这边就判断如果接收到的资讯不是 null
就会输出监听到的东西。
实际执行情况:
利用 stdout 与 stderr 分别处理串流输出
这部分我会搭配上面的 stdin 使用,
上面有提到这两个都是串流输出但是主要是将预期与非预期的输出结果作分流。
在 browser 的开发人员工具可以明显分出 error 和 info 的 console,
你只要想成以下这样就好
console.log() -> process.stdout()console.error() -> process.stderr()
但是在 terminal 这块我看不出来差异 Orz
那这边就用如果输入 Robin is handsome
就代表是预期的,
并且输出串流 ✅Very smart! That is truth.
。
反之如果输入 Kevin have girlfriend
就代表这不是预期的,
并且输出串流 ❌Liyer! That is not truth.
。
而其余情况就不多做事。
process.stdin.setEncoding('utf-8');process.stdin.on('readable', () => { let input; while ((input = process.stdin.read()) !== null) { const command = input.trim(); \\去除两端的空白字符或是断行 console.log(`我监听到东西啦 -> ${command}`) if (command === 'Robin is handsome') process.stdout.write("✅Very smart! That is truth.") if (command === 'Kevin have girlfriend') process.stderr.write("❌Liyer! That is not truth.") if (command === 'exit') process.exit(); }});
如果不想要连同换行 也被log 出来,可以改用以下判断
if(command!== '') console.log(`我监听到东西啦 -> ${command}`)
另外如果不想使用trim() 可以在判断的最后方加入'\n'
也可以正常运行唷~
实际执行情况:
实际使用!建立简单的 CLI 来查询鼠年马拉松的文章登记情况
这边就直接实战,以直接想查询自己在六角学院这次办的鼠年马拉松,登记情况为例,刚好六角学院这边有提供 API 真的方便。
虽然说有人有做网页版满方便且漂亮的,但是实际上还是要开浏览器,
如果想单纯使用 terminal 查询就可以参考我这个範例喔~
先看成果~
我的使用情境是我希望我能够打 get 关键字然后再输入我的keyID来查询我的文章登记情况,像我的keyID就是 188
那我就希望我只需要在 termnial 输入 get 188
,就能拿到我要的东西。
来吧~
首先写一个获取鼠年马拉松API资料的的module。
//getW3hexschool.jsconst request = require('request');const w3hexschool_API_URL = 'https://raw.githubusercontent.com/hexschool/w3hexschool-API/master/data.json'module.exports = function (keyID) { return new Promise((resolve, reject) => { request.get({ 'url': w3hexschool_API_URL }, (error, response) => { if (error) reject(new Error(error)); resolve(response); }); });}
再来就是今天学到的使用 process 标準输出入
// cli.jsconst getW3hexschool = require('./getW3hexschool');process.stdin.setEncoding('utf-8');process.stdin.on('readable', () => { let input; while ((input = process.stdin.read()) !== null) { const command = input.trim(); if (command.includes('get') && command.split(' ').length === 2) { const keyID = parseInt(command.split(' ')[1]); getW3hexschool(keyID).then(val => { const targetVal = (JSON.parse(val.body)).filter((item) => { return item.keyID === keyID; }); console.log('-------------------------------------') process.stdout.write(`name: ${targetVal[0].name}\n`); process.stdout.write(`blogUrl: ${targetVal[0].blogUrl}\n`); process.stdout.write(`updateTime: ${targetVal[0].updateTime}\n`); process.stdout.write('blogList:\n'); targetVal[0].blogList.forEach(item => { process.stdout.write(`Title: ${item.title}\n`); process.stdout.write(`Url: ${item.url}\n`); }); console.log('-------------------------------------'); }); }; if (command === 'exit') process.exit(); }});
我这边的判断方法是
先判断 user 输入的字有没有包含 get
,且中间以空白为区隔,区隔出来长度必须是2 ,如果成立就拿区隔出来的第二个值当作是 keyID,再把 拿到的资料透过filter将keyID做筛选,最后列出来。
当然你也可以将这程式改成你要的,可能你想要输入名字之类的,就依照您自己的需求做改良。(,,・ω・,,)
以上。
有问题都可以留言问我
感谢各位读者的观看
参考文献
Node doc
process.stdin
Node.js 基于流将日志、错误分别写入不同文件