Streams 是一个数据集——和数组、字符串一样。不同的是streams的数据可能不能马上全部获取到,他们不需要在内存中。这样使得streams在处理大数据集或者来自外部的数据源的数据块上能发挥很大的作用。
Streams在Node.js中非常重要的一个模块,其数据主要分为二进制和对象模式,应用广泛。一个流是一个具备了可读、可写或既可读又可写能力的接口,通过这些接口,我们可以和、HTTP请求来交互,实现数据从一个地方流动到另一个地方的功能。
二进制模式的每个对块为buffer/string
对象模式.流内部处理的是一系列普通的对象
Stream(流)的类型:
- Stream.Readable -可读的流
- Stream.Writable -可写的流
- Stream.Duplex -可读写的流
- Stream.Transform -在读写过程中可以修改和变换数据的Duplex (zlib, createDeflate())
Stream.Readable
主要用来提供数据,外部来源的数据均会储存到内部的buffer数组缓存起来.主要是以下两种模式:
-
flowing.自动从系统底层读取数据,并通EventEmitter接口事件尽快将数据提供给应用.
可通过以下两种途径切换到paused模式:
- 不存在管道目标.直接使用stream.paused
- 存在管道目标,直接取消data事件监听,并调用stream.unpipe()移除管道.
let fs = require('fs');//456789
let rs = fs.createReadStream('./13.stream/2.txt',{
start:3,
end:8,
highWaterMark:3
});
rs.on('data',function(data){
console.log(data.toString());
});
rs.on('end',function(){
console.log('over');
});
rs.on('error',function(err){
console.log(err);
});
rs.on('open',function(){
console.log('open');
});
rs.on('close',function(){
console.log('close');
});
-
paused.需要手动使用stream.read()方法从流中读取数据片段.可以直接指定读取数据的长度.
可通过以下三种途径切换到flowing模式:
- 可通过监听'data'事件,
- 调用stream.resume(),
- 调用stream.pipe()方法将数据发送到writable
let {Readable} = require('stream');
let util = require('util');
util.inherits(Counter,Readable);
function Counter(){
Readable.call(this);
this.index = 3;
}
Counter.prototype._read = function(){
if(this.index-->0){
this.push(this.index+'');
}else{
this.push(null);
}
}
let counter = new Counter();
counter.on('data',function(data){
console.log(data.toString())
});
可读流默认情况下都是在暂停模式
Stream.Writable
消费数据的stream.从readble stream中获取数据.然后对得到的chunk快进行处理.
const { Writable } = require('stream');
const outStream = new Writable({
write(chunk, encoding, callback) {
console.log(chunk.toString());
callback();
}
});
process.stdin.pipe(outStream);
// chunk通常是一个buffer,除非我们配置不同的流。
// encoding是在特定情况下需要的参数(utf8),通常我们可以忽略它。
// callback是在完成处理数据块后需要调用的函数。这是写数据成功与否的标志。若要发出故障信号,请用错误对象调用回调函数。
Stream.Duplex
在同一个对象上同时实现可读和可写,并且可读性和可写性操作完全独立于彼此,仅仅是将两个特性组合成一个对象。
const { Duplex } = require('stream');
const inoutStream = new Duplex({
write(chunk, encoding, callback) {
console.log(chunk.toString());
callback();
},
read(size) {
this.push(String.fromCharCode(this.currentCharCode++));
if (this.currentCharCode > 90) {
this.push(null);
}
}
});
inoutStream.currentCharCode = 65;
process.stdin.pipe(inoutStream).pipe(process.stdout);
双工流的可读性和可写性操作完全独立于彼此。这仅仅是将两个特性组合成一个对象。
Stream.Transform
转换流可以理解为时一个更加有趣的双工流,我们只需要实现一个transfrom方法,将两者结合起来.
const { Transform } = require('stream');
const upperCaseTr = new Transform({
transform(chunk, encoding, callback) {
this.push(chunk.toString().toUpperCase());
callback();
}
});
process.stdin.pipe(upperCaseTr).pipe(process.stdout)
关于stream的相关api及源码解析,将会在年后,陆续补充