为什么在完成之前,“完成”事件在Node.js转换stream上触发?

我期待只有当传递给_flush的callback完成后才能触发callback,但是在_flush完成之前触发callback。 为什么?

var stream = require('stream').Transform(); // Nothing interesting here stream._transform = function (chunk, enc, next) { next(); }; // _flush makes an async call. stream._flush = function (callback) { console.log("Expecting 1st: Entering _flush "); return process.nextTick(function () { console.log("Expecting 2nd: Done with _flush"); callback(); }); }; stream.on('finish',function () { console.log("Expecting 3rd: Entering finish callback-- should be flushed now."); }); stream.end("chunk"); 

完成的node.jsstream文档说,只有当所有数据已经​​被刷新到底层系统时,才触发事件。

看看Node的转换stream实现的源代码,看起来只有在调用_flushcallback函数时才会触发_flush

 this.once('prefinish', function() { if (util.isFunction(this._flush)) this._flush(function(er) { done(stream, er); }); else done(stream); }); 

要么我错过了什么,或者这是一个节点的转换stream的错误。 我认为这是前者,但没有发现我的问题。 谢谢你的帮助!

更新:请注意,如果我将调用process.nextTick()replace为sleep模块提供的同步调用,那么问题就会消失。 这个问题只能由_flush的asynchronous调用触发。

在节点v0.10中, _flush()在'finish'被调用 ,所以更明显地看到这是预期的。

然而在master(v0.11.x)中,它看起来像是一个新的“预先”事件被发明了,并且改变了一些事情。 但是,如果你看代码 ,你会看到prefinish()被调用, 触发_flush() 。 当prefinish()在发射“prefinish”之后返回时,则发出“finish”。 在执行此操作之前,不会等待调用_flush()callback。

所以这两个版本的结果是相同的。 现在是否应该改变行为是一个单独的问题。 你可以创build一个关于情况的github问题,看看是否有兴趣修改行为。

“完成”事件没有直接控制,“_flush”不是可写入stream的一部分。

使用PassThrough,在'finish'事件之后执行'this.resume()',你将得到一个'end'事件。

或者,你可以按照pull请求: https : //github.com/nodejs/node-v0.x-archive/pull/7612

或者使用一个模块: https : //github.com/TomFrost/FlushWritable