我有一个NodeJS流转换,当输入结束时需要输出一些内部状态。
作为类比,考虑将传入数据分成行的转换。当输入数据结束时,必须输出任何(非换行终止)数据。
我该怎么做?
(我已经尝试了_flush,但是当我write(null)
进入变换时,它不会被调用。)
var Transform = require('stream').Transform;
var util = require('util');
exports.createLinesTransform = createLinesTransform;
function createLinesTransform(options) {
return new LinesTransform(options);
}
function LinesTransform(options) {
options = options ? options : {};
options.objectMode = true;
Transform.call(this, options);
this._buf = '';
this._last_src = undefined;
}
util.inherits(LinesTransform, Transform);
LinesTransform.prototype._transform = function(chunk, encoding, done) {
console.log('chunk', chunk, '_buf', this._buf);
this._buf += chunk.payload;
for (var i = 0; i < this._buf.length; i++) {
if (this._buf.charAt(i) === '\n') {
this.push({src: chunk.src, payload: this._buf.slice(0, i)});
this._last_src = chunk.src;
this._buf = this._buf.slice(i + 1);
}
}
done();
}
// this doesn't get called when the input stream ends
LinesTransform.prototype._flush = function(done) {
console.log('_flush');
this.push({src: this._last_src, payload: this._buf});
done();
}
和测试:
it('should make a working LinesTransform', function() {
var lines = createLinesTransform();
var rxd = [];
lines.on('data', function(data) {
console.log('data', data);
rxd.push(data);
});
var ret = lines.write({src:{},payload:'hel'});
assert.deepEqual([], rxd);
ret = lines.write({src:{},payload:'lo'});
assert.deepEqual([], rxd);
lines.write({src:{},payload:' world!\na second'});
assert.deepEqual([{"src":{},"payload":"hello world!"}], rxd);
lines.write({src:{},payload:'line\n'});
assert.deepEqual([{"src":{},"payload":"hello world!"},
{"src":{},"payload":"a secondline"}],
rxd);
lines.write({src:{},payload:'and some trailing data'});
assert.deepEqual([{"src":{},"payload":"hello world!"},
{"src":{},"payload":"a secondline"}],
rxd);
lines.write(null);
lines.end();
// this last assert fails
assert.deepEqual([{"src":{},"payload":"hello world!"},
{"src":{},"payload":"a secondline"},
{"src":{},"payload":"and some trailing data"}],
rxd);
});
答案 0 :(得分:1)
_flush
是正确的做法,我需要在测试中添加一个短暂的延迟才能使其正常工作。