我知道如何在Node的新Streams2
库中使用可写流,但不知道如何使用可读流。
例如,围绕dgram
模块的流包装器:
var dgram = require('dgram');
var thumbs = {
twiddle: function() {}
};
var defaults = {
address: '0.0.0.0',
type: 'udp4',
port: 12345,
broadcast: null,
multicast: null,
multicastTTL: 1
};
var UDPStream = function(options) {
if (!(this instanceof UDPStream))
return new UDPStream(options);
Duplex.call(this);
options = options || {};
this.address = options.address || defaults.address;
this.type = options.type || defaults.type;
this.port = options.port || defaults.port;
this.broadcast = options.broadcast || defaults.broadcast;
this.multicast = options.multicast || defaults.multicast;
this.multicastTTL = options.multicastTTL || defaults.multicastTTL;
this._socket = dgram.createSocket(this.type, setup.bind(this));
this._socket.on('message', this.push.bind(this));
};
util.inherits(UDPStream, Duplex);
var setup = function() {
if (this.multicast) {
this._socket.addMembership(this.multicast);
this._socket.setMulticastTTL(this.multicastTTL);
this.destination = this.multicast;
} else {
// default to using broadcast if multicast address is not specified.
this._socket.setBroadcast(true);
// TODO: get the default broadcast address from os.networkInterfaces() (not currently returned)
this.destination = this.broadcast || '255.255.255.255';
}
};
UDPStream.prototype._read = function(size) {
thumbs.twiddle();
};
UDPStream.prototype._write = function(chunk, encoding, callback) {
this._socket.send(chunk, 0, chunk.length, this.port, this.destination);
callback();
};
module.exports = UDPStream;
除了_read
实现之外,一切都有意义。这简直是在玩弄拇指,因为我不明白我应该在那里做什么。当udp套接字发出新消息时,我的数据会被推送,但我无法暂停或恢复底层资源。应该是什么样子?
_read是暂停-恢复机制的一部分。从NodeJS API文档
当数据可用时,通过调用readable.prush(chunk)。如果push返回false,则应该停止阅读当再次调用_read时,您应该开始推送更多数据
因此,在_write函数中,如果socket.send
调用因返回false或调用带有错误的回调而失败,则应暂停流。_read
就可以简单地做this._paused = false
可能看起来像这样。
UDPStream.prototype._read = function() {
this._paused = false;
}
UDPStream.prototype._write = function(chunk, encoding, callback) {
if(!this._paused)
this._socket.send(chunk, 0, chunk.length, this.port, this.destination);
};
答案很简单:如果真的没有办法对底层资源应用背压,那么_read
实现就是空的。流将负责对推送的数据进行排队,直到它到达highWaterMark
,但不能保证超过该点。文档说,你应该"只要数据可用,就简单地提供数据"。