双工流与转换流介绍
双工流
双工流 Duplex
可以实现流的可读和可写功能,即同时实现 Readable
和 Writable
。实现双工流需要进行以下 3 步。
-
继承
Duplex
类。 -
实现
_read()
方法。 -
实现
_write()
方法。
使用代码演示上面的 3 个步骤,其形式如下:
const Duplex = require('stream').Duplex;
const myDuplex = new Duplex({
_read(size) {
// ...
},
_write(chunk, encoding, callback) {
// ...
}
});
【例10.4】双工流的使用。(实例位置:资源包\源码\10\04)
创建一个 .js
文件,其中创建双工流对象,并分别实现双工流的 _read()
方法和 _write()
方法;然后通过监听 data
事件实现数据的读取,通过调用 write()
方法实现数据的写入;最后分别监听 end
事件和 finish
事件,确认读取和写入操作完成。代码如下:
const stream = require('stream');
var duplexStream = stream.Duplex();
duplexStream._read = function () {
this.push('读取数据');
this.push(null)
}
duplexStream._write = function (data, enc, next) {
console.log(data.toString());
next();
}
duplexStream.on('data', data => console.log(data.toString()));
duplexStream.on('end', data => console.log('读取完成'));
duplexStream.write('写入数据');
duplexStream.end();
duplexStream.on('finish', data => console.log('写入完成'));
运行结果如图10.6所示。

转换流
转换流 Transform
其实也是双工流,它与 Duplex
的区别在于,Duplex
虽然同时具备可读流和可写流的功能,但两者是相对独立的,而 Transform
中可读流的数据会经过一定的处理过程自动进入可写流。需要说明的是,从可读流到可写流,它们的数据量不一定相同。例如,常见的压缩、解压缩用的zlib就使用了转换流,压缩和解压缩前后的数据量明显不同。
实现转换流需要进行以下两步。
-
继承
Transform
类。 -
实现
_transform()
方法。_transform()
方法用来接收数据,并产生输出(需要调用this.push(data)
,如果不调用,则接收数据但不输出)。当数据处理完后,必须执行callback(err, data)
回调函数,该函数中的第一个参数用于传递错误信息,第二个参数用来输出数据(效果和this.push(data)
相同),但参数可以省略。
使用代码演示上面的两个步骤,其形式如下:
const Stream = require('stream')
class TransformReverse extends stream.Transform {
constructor() { //继承构造函数
super()
}
_transform(data, encoding, callback) {
this.push(data);
callback();
}
}
【例10.5】转换流的使用。(实例位置:资源包\源码\10\05)
创建一个 .js
文件,其中首先通过继承 Transform
自定义一个转换流,在自定义的转换流中重写 _transform()
方法时,实现将写入数据进行反转输出的功能;然后使用转换流的 write()
方法写入数据,并通过监听 data
事件实现数据的读取;最后分别监听 end
事件和 finish
事件,确认读取和写入操作完成。代码如下:
const Stream = require('stream');
class TransformStream extends stream.Transform {
constructor() {
super()
}
_transform(data, encoding, callback) {
//将写入的数据进行反转
const res = data.toString().split('').reverse().join('');
this.push(res) //输出反转后的数据
callback()
}
}
var transformStream = new TransformStream();
transformStream.on('data', data => console.log(data.toString()))
transformStream.on('end', data => console.log('读取完成'));
transformStream.write('写入数据');
transformStream.end()
transformStream.on('finish', data => console.log('写入完成'));
运行结果如图10.7所示。观察图10.7,发现写入的数据在输出时,实现了反转输出。
