请考虑以下情形。我有两个节点转换流:
转换流1
function T1(options) {
if (! (this instanceof T1)) {
return new T1(options);
}
Transform.call(this, options);
}
util.inherits(T1, Transform);
T1.prototype._transform = function(chunk, encoding, done) {
console.log("### Transforming in t1");
this.push(chunk);
done();
};
T1.prototype._flush = function(done) {
console.log("### Done in t1");
done();
};
转换流2
function T2(options) {
if (! (this instanceof T2)) {
return new T2(options);
}
Transform.call(this, options);
}
util.inherits(T2, Transform);
T2.prototype._transform = function(chunk, encoding, done) {
console.log("### Transforming in t2");
this.push(chunk);
done();
};
T2.prototype._flush = function(done) {
console.log("### Done in t2");
done();
};
并且,我想在返回响应之前应用这些转换流。我有一个简单的HTTP服务器,在每个请求中,我获取资源并希望将这些转换应用于此获取的资源,然后将第二个转换的结果发送到原始响应:
var options = require('url').parse('http://localhost:1234/data.json');
options.method = 'GET';
http.createServer(function(req, res) {
var req = http.request(options, function(httpRes) {
var t1 = new T1({});
var t2 = new T2({});
httpRes
.pipe(t1)
.pipe(t2)
.on('finish', function() {
// Do other stuff in here before sending request back
t2.pipe(res, { end : true });
});
});
req.end();
}).listen(3001);
最终,finish
事件永远不会被调用,并且请求会挂起并超时,因为响应永远不会被解决。我注意到如果我只是将t2
传递给res
,它似乎工作正常:
.pipe(t1)
.pipe(t2)
.pipe(res, { end : true });
但是,这种情况似乎不可行,因为我需要在返回响应之前做一些额外的工作。
答案 0 :(得分:1)
发生这种情况是因为您需要让节点知道流正在某处消耗,否则最后一个流只会填满缓冲区,并且考虑到您的数据比highwaterMark选项(通常为16)更长,然后停止等待要消耗的数据。
有三种方法可以完整地使用流:
read
方法"data"
事件(主要是stream.on("data", someFunc)
)。最后一个选项是最快的,但会导致使用流而不查看内存使用情况。
我还注意到使用"finish"
事件可能有点误导,因为它在读取最后一个数据时被调用,但不一定被发出。在转换流上,因为它是可读的,所以使用"end"
事件要好得多。