到 stdout 的节点管道——如何判断是否耗尽?

Node pipe to stdout -- how do I tell if drained?

关于确定是否需要等待 process.stdout 上的 drain 事件的标准建议是在写入时检查它是否 returns false。

我应该如何检查我是否已将另一个流传输到它?在实际写入所有输出之前,该流似乎可以发出 finish 。我可以做类似的事情吗?

upstreamOfStdout.on('finish', function(){
  if(!process.stdout.write('')) {
    process.stdout.on('drain', function() { done("I'm done"); });
  }
  else {
    done("I'm done"); 
  }
});
upstreamOfStdout.pipe(process.stdout);

我更喜欢不依赖于任何流内部的答案。只要流符合节点流接口,执行此操作的规范方法是什么?

编辑

更大的上下文是一个包装器:

new Promise(function(resolve, reject){
  stream.on(<some-event>, resolve);
  ... (perhaps something else here?)
});

其中 stream 可以是 process.stdout 或其他东西,其中有另一个直通流。

只要 resolve 被调用,我的程序就会退出——我假设 Promise 代码使程序保持活动状态,直到所有承诺都已解决。

这种情况我遇到过好几次了,一直都是用hack来解决的(比如process.stdout里面有几个私有成员很有用。)但是我真的很想一次解决这个问题对于所有人(或者知道这是一个错误,这样我就可以跟踪问题并至少在问题解决后修复我的黑客):我如何判断另一个流的下游何时完成其输入的处理?

首先,据我在 documentation 中所见,该流从不发出 finish 事件,因此您不太可能依赖它。

此外,从上面提到的文档来看,drain 事件似乎用于在 .write 方法后通知用户 stream 何时准备好接受更多数据返回 false。在任何情况下,您都可以推断出这意味着所有其他数据都已写入。从 write 方法的文档中我们确实推断出 false 值(又名请停止推送数据)不是强制性的,您可以随意忽略它,但后续数据可能会被填充到内存中,让用它来成长。

因此,根据我对唯一文档的假设,我想您可以依靠 drain 事件来了解何时所有数据都得到妥善处理或可能被清除。

也就是说,在我看来,也没有明确的方法可以明确知道何时所有数据都已有效地发送到控制台。

最后,你可以监听管道streamend事件来知道它什么时候被完全消耗,不管它是否已经写入控制台或者数据还在缓冲在控制台流中。 当然,你也可以随意忽略这个问题,因为完全消耗的流应该由 node.js 很好地处理,因此被丢弃,一旦你将它传输到第二个流,你就不必再处理它了。

不是直接写入 process.stdout,而是创建一个自定义可写对象(如下所示)作为副作用写入标准输出。

const { Writable } = require('stream');
function writeStdoutAndFinish(){
  return new Writable({
    write(chunk, encoding, callback) {
      process.stdout.write(chunk,callback);
    },
  });
};

writeStdoutAndFinish() 的结果将发出 finish 事件。

async function main(){
  ...
  await new Promise((resolve)=>{
    someReadableStream.pipe(writeStdoutAndFinish()).on('finish',()=>{
      console.log('finish received');
      resolve();
    }) 
  });
  ...
}

实际上,我不认为上述方法在行为上与

不同
async function main(){
  ...
  await new Promise((resolve)=>{
    (someReadableStream.on('end',()=>{
      console.log('end received');
      resolve();
    })).pipe(process.stdout)
  });
  ...
}