Node.js 具有可写流的消息块
我正在使用nodejs0.10和(websocketlib) 我想实现我自己的Node.js 具有可写流的消息块,node.js,stream,Node.js,Stream,我正在使用nodejs0.10和(websocketlib) 我想实现我自己的stream.Writable类来发送websocket消息。 我的限制是: 在将写入的数据发送到websocket之前,我必须将其分割成10KB的数据块,并预先向它们发送一个JSON头 最后一个区块的JSON标头必须包含“last:true” 例如,如果我打电话: myStream = new FoobarStream; myStream.write(<a buffer of 7KB>); myStr
stream.Writable
类来发送websocket消息。我的限制是:
- 在将写入的数据发送到websocket之前,我必须将其分割成10KB的数据块,并预先向它们发送一个JSON头
- 最后一个区块的JSON标头必须包含“last:true”
myStream = new FoobarStream;
myStream.write(<a buffer of 7KB>);
myStream.end(<another buffer of 7KB>);
myStream=newfoobarstream;
myStream.write();
myStream.end();
然后,我希望我的流以两条消息的形式发送此数据:第一条消息的JSON头后跟10KB的数据,第二条消息的JSON头(包含“last:true”字段)后跟4KB的数据
这意味着我必须临时发送数据,这意味着我必须找到一种方法来知道何时写入消息的最后一个数据,因为我必须将这个“last:true”字段写入JSON头中
我不知道如何只继承stream.writeable的\u write()
方法。似乎我无法在_write()中知道是否调用了end(),因此我无法用“last:true
”标记我的JSON头
这是否意味着我必须继承stream.writeable的end()
方法
有什么想法吗?可以定义自己的
end
方法并从那里开始处理。但这意味着要从原来的end
方法重写一些代码
相反,您可以保留一个内部缓冲区,并在prefinish
或finish
事件中处理最后一块数据块。下面是一个简单的例子:
function FoobarStream(options){
Writable.call(this, options);
this.on('prefinish', function(){
if(this._buffer){
//process the last chunk
process.stdout.write('footer: '+ this._buffer+ "\n");
}
});
}
FoobarStream.prototype._write = function(chunk, encoding, cb){
if(this._buffer){
//process other chunks here
process.stdout.write('header: ' + this._buffer+ "\n");
this._buffer = chunk;
}
else
this._buffer = chunk;
cb();
}
myStream = new FoobarStream;
myStream.write('first line');
myStream.write('second line');
myStream.end('last line');
/*
outputs:
header: first line
header: second line
footer: last fine
*/
您可以将对接收器(底层可写流资源)的写入延迟到
process.nextTick
,这将允许您在写入结果之前检查流上是否触发了finish
(0.10中没有prefinish
)事件。以下是您可以运行的示例:
var Stream = require('stream');
var Util = require('util');
// Create a readable to test our FoobarStream out
var readable = new Stream.Readable();
var finished = false;
readable._read = function () {
if (finished) {
this.push(new Buffer('world'));
return this.push(null);
}
this.push(new Buffer('hello '));
finished = true;
};
// Create the FoobarStream
var FoobarStream = function (options, sink) {
Stream.Writable.call(this, options);
this.sink = sink;
this.finished = false;
this.on('finish', function () {
this.finished = true;
});
};
Util.inherits(FoobarStream, Stream.Writable);
FoobarStream.prototype.serialize = function (chunk) {
var header = new Buffer(JSON.stringify({some: 'header', last: this.finished}));
return Buffer.concat([header, chunk]);
};
FoobarStream.prototype._write = function (chunk, encoding, callback) {
var self = this;
process.nextTick(function () {
self.sink.write(self.serialize(chunk));
});
callback();
}
readable.pipe(new FoobarStream(null, process.stdout));
控制台中的输出:
$ node index.js
{"my":"header","last":false}hello
{"my":"header","last":true}world