初识Node.js中的stream(流):

129 阅读4分钟

stream(流)是什么?

流(stream)在 Node.js 中是处理流数据的抽象接口(abstract interface)。 stream 模块提供了基础的 API 。使用这些 API 可以很容易地来构建实现流接口的对象。

Node.js 提供了多种流对象。 例如, HTTP 请求process.stdout 就都是流的实例。

流可以是可读的、可写的,或是可读写的。所有的流都是 EventEmitter 的实例。

流是一种抽象的数据结构。想象水流,当在水管中流动时,就可以从某个地方(例如自来水厂)源源不断地到达另一个地方(比如你家的洗手池)。我们也可以把数据看成是数据流,比如你敲键盘的时候,就可以把每个字符依次连起来,看成字符流。

Node.js 中有四种基本的流类型:


所有使用 Node.js API 创建的流对象都只能操作 strings 和 Buffer(或 Uint8Array) 对象。但是,通过一些第三方流的实现,你依然能够处理其它类型的 JavaScript 值 (除了 null,它在流处理中有特殊意义)。 这些流被认为是工作在 “对象模式”(object mode)。

Readable (可读流)

Readable 事件:

readable:事件将在流中有数据可供读取时触发。在某些情况下,为 'readable' 事件添加回调将会导致一些数据被读取到内部缓存中。

data:事件会在流将数据传递给消费者时触发。当流转换到 flowing 模式时会触发该事件。调用 readable.pipe()readable.resume() 方法,或为 'data' 事件添加回调可以将流转换到 flowing 模式。 'data' 事件也会在调用 readable.read() 方法并有数据返回时触发。

end: 事件将在流中再没有数据可供消费时触发。

close: 当底层资源,如文件,已关闭时触出。

error:在接收数据中出错是触发。

Readable 方法:

read([size]):从流中读数据.数据可以是String、Buffer、null(下面代码会有),当指定size,那么只读仅限于那个字节数

setEncoding(encoding):设置read()请求读取返回String时使用的编码

pause():暂停从该对象发出的data事件

resume():恢复从该对象发出的data事件

创建一个Readable(可读流):

let fs = require('fs');let path = require('path');
// 返回的是一个可读流对象let rs = fs.createReadStream(path.join(__dirname,'1.txt'),{    flags:'r', // 文件的操作是读取操作    encoding:'utf8', // 默认是null null代表的是buffer    autoClose:true, // 读取完毕后自动关闭    highWaterMark:3,// 默认是64k  64*1024b 汉字是三个字节    start:0, // 123 456 789      //end:9 // 包前又包后});// 默认情况下 不会将文件中的内容输出// 内部会先创建一个buffer先读取3b
// 流动模式会疯狂的触发data事件,直到读取完毕//rs.setEncoding('utf8');rs.on('open',function(){    console.log('文件打开了')});// newLisenterrs.on('data',function(data){ // 暂停模式 -> 流动模式    console.log(data);   // rs.pause(); // 暂停方法 表示暂停读取,暂停data事件触发});
rs.on('readable',function(res){     console.log('有数据了');  });rs.on('error',function(err){    console.log(err);});rs.on('end',function(){    console.log('end')});rs.on('close',function(){    console.log('关闭')});

输出的:
文件打开了 0123456789 有数据了 end 关闭

Writable (可写流)

Writable事件:

write(chunk,[encoding],[callback]):将数据写入流。chunk(数据块)中包含要写入的数据,encoding指定字符串的编码,callback指定当数据已经完全刷新时执行的一个回调函数。如果成功写入,write()返回true.

end([chunk],[encoding],[callback]):与write()相同,它把Writable对象设为不再接受数据的状态,并发送finish事件。

Writable方法:

drain:在write()调用返回false后,当准备好开始写更多数据时,发出此事件通知监视器。

finish:当end()在Writable对象上调用,所以数据被刷新,并不会有更多的数据被接受时触发


创建一个Writable:

let fs = require('fs');let path = require('path');
// 写的时候文件不存在 会创建文件let ws = fs.createWriteStream(path.join(__dirname,'1.txt'),{    highWaterMark:3,    autoClose:true,    flags:'w',    encoding:'utf8',    mode:0o666,    start:0,});// 写内容的时候 必须是字符串或者bufferfor(var i = 0;i<4;i++){   let flag =  ws.write(i+''); // 第一次写一个字符   console.log(flag)}ws.on('drain',function(){    console.log('drain')});

控制台打印:
true true false falsedrain1.txt 的内容是: 0123