双工流
- 双工流特点:
- 既可读,又可写。(读写之间可以没有关系)
- 同时实现了 Readable 和 Writable 的流,即可以作为上游生产数据,又可以作为下游消费数据,这样可以处于数据流动管道的中间部分
rs.pipe(rws1).pipe(rws2).pipe(rws3).pipe(ws);
1. Duplex实现
由于js没有多继承,但又需要继承Readable和Writable,所以就需要继承Duplex类,而这个类继承了Readable和Writable
const { Duplex } = require('stream')
class MyDuplex extends Duplex{
_read(){
this.push('xxx'); // on监听的时候需要push xxx
this.push(null) // on结束监听的时候需要push null
}
// 这里的_read和_write可以有关系,也可以没关系,这个无所谓
_write(chunk, encoding, cb){
console.log(chunk.toString())
cb();
}
}
let md = new MyDuplex()
// on('data')会调用Duplex类的read方法,read方法会调用子类MyDuplex的_read方法,然后将xxx放到数组中,chunk就是xxx
md.on('data', (chunk) => {
console.log(chunk.toString())
})
md.write('ok') // 会先打印ok,再监听到data,因为write方法会调用Duplex的write方法,write方法会调用子类MyDuplex的_write方法,至此都是同步的,关键看自己实现的_write是否为同步,可见这里是同步的,所以整个ws.write就是同步的。而on('data')是订阅发布,是异步的,所以先打印ok,再打印data中的内容
2. 双工流使用场景
以下可以看到 client 就是一个 Duplex,可写流用于向服务器发送消息,可读流用于接受服务器消息,两个流内的数据并没有直接的关系。
var net = require('net');
//创建客户端
var client = net.connect({port: 1234}, function() {
console.log('已连接到服务器');
client.write('Hi!');
});
//data事件监听。收到数据后,断开连接
client.on('data', function(data) {
console.log(data.toString());
client.end();
});
//end事件监听,断开连接时会被触发
client.on('end', function() {
console.log('已与服务器断开连接');
});