Node 中的流(Stream)

空话

朴(piáo)老湿的九浅一深 Node.js 貌似没有细致引见 Stream 模块。本身对这个模块算是比较熟习,随手也 PO 上来备忘一下吧。

又是空话

假如说 Activity、Service、Content Provider 和 Broadcast Receiver 并称 Android 四大组件的话,那末 Node 的「N 大模块」内里一定要有 Stream。

类似于 *nix 将险些一切装备笼统为文件一样,Node 将险些一切 IO 操纵都笼统成了 Stream 的操纵。Stream 是一个笼统的观点,总之就是会冒数据(以 Buffer 为单元),或许可以吸取数据的东西。

为何须要 Stream 呢?

在 Node 里读取一个文件的内容:

var fs = require('fs')

fs.readFile('/etc/hosts', function (err, buffer) {
  if (err) {
    return console.error(err.stack)
  }

  console.log(buffer.toString('utf8'))
})

关于大文件操纵,一口气悉数读入内存肯定是不可的,科学的做法是一份一份地读:

var fs = require('fs')

fs.open('/etc/hosts', 'r', function (err, fd) {
  if (err) {
    return console.error(err.stack)
  }

  // 内啥,我想演示一下用 fs.read 逐片逐片读文件的,但那玩意着实太烦,
  // 所以我懒得写了。本身看文档。
})

很烦对吧?每次读若干?这些每每不是我们须要体贴的,因而就有了 Stream。Node 对这类传统的读取历程隐蔽到了文件读取 Stream 中:

var fs = require('fs')
fs.createReadStream('/etc/hosts').pipe(process.stdout)

没错,就两行代码,将 hosts 文件的内容显示出来。

之前的 Stream

在 Node 的初期版本中,Stream 只是一个简朴的继续自 EventEmitter 的类。以文件读取流为例子,一旦最先读取,数据就会源源不停地读出,触发 'data' 事宜——嗯一最先的确是一个不错的设想,但假如你想等一下,比方说守候某个回调后再最先处置惩罚这些数据。。。好吧,每一片数据只会冒出来一次,没人消耗的话它就没了;OK 你想到了用 pause-stream「停息」一下这个流,等下再消耗?完了,数据会暂存在内存中,逐步聚集,然后,你懂了。

如今的 Stream

固然并不是说本来不停冒 'data' 的读取体式格局是不好的,只是说它关于某些情形,比方文件读取,比方收集传输,没办法掌握读取速率罢了。收集传输注定是没办法掌握读取速率的,人家给你若干你都得吃进去;但文件读取,能不能按须要,处置惩罚若干读若干呢?

Node 0.10.X 就对 Stream 做了如许的修改:默许情况下,Node 会尽能够运用「拉」形式,也就是说只要 pipe 链末尾的流消耗者真正须要数据的时刻,数据才会从泉源被掏出,然后顺着管子一起抵达消耗者。

如许我就可以把管子插……

Stream 的精华在于 .pipe() 嗯。

下载文件?So easy

引荐一个牛逼哄哄的库:request,Stream API 运用到极致的 HTTP(S) 要求库。

var fs = require('fs')
  , request = require('request')

var writer = fs.createWriteStream('hexie.pkg')
// 'close' 和 'error' 事宜分别是写入完成和发作毛病,懒得写,看文档。

request('http://xxxxxxx.xxx/abs123.avi').pipe(writer)

fs.createWriteStream() 创建了一个新文件并返回了该文件的 Writable Stream;request() 发起了一个 HTTP 要求并返回一个 Readable Stream。将这两个 Stream 经由过程 .pipe() 一对接,request() 的下载流量就被直接导到当地文件并写入磁盘,奇异吧?

模仿 HTML POST 表单上传也是 So easy

引荐一下朴老湿好基友苏千大神(@Python发烧友)的 formstream,合营 request 几乎堡垒。

var request = require('request')
  , FormStream = require('formstream')

var form = FormStream()
  .field('title', 'ni dong de')
  .file('attachment', 'hexie.pkg')

var upload = request.post('http://xxxx.xxx/upload', {
  headers: form.headers()
}, function (err, res, body) {
  // ... 略
})

form.pipe(upload)

末了,照样空话

末了,末了,还得谢谢老雷(@雷宗民)的 Node.js API 翻译设计,俺就是翻译完 Stream 章节才明白上面这些精华的。

以上。

    原文作者:XiNGRZ
    原文地址: https://segmentfault.com/a/1190000000357044
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞