节点管道到stdout - 如何判断是否已耗尽?

时间:2015-10-17 19:01:25

标签: node.js stream

确定是否需要等待drain process.stdout事件的标准建议是检查写入时是否返回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或其他内容,其中包含另一个直播流。{/ p>

我的程序在调用resolve时退出 - 我假设Promise代码使程序保持活动状态,直到所有承诺都得到解决。

我已经多次遇到这种情况,并且总是使用黑客来解决问题(例如process.stdout中有几个私有成员很有用。)但我真的想一劳永逸地解决这个问题。 (或者知道这是一个错误,所以我可以跟踪问题并在解决问题时解决我的问题,至少):我如何判断另一个下游的流何时完成处理输入?

2 个答案:

答案 0 :(得分:2)

首先,据我所知documentation,该流不会发出finish事件,因此您不太可能依赖此事件。

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

正因为如此,基于我对单独文档的假设,我想您可以依赖false事件来了解所有数据何时处理得很好或者可能被刷新。

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

最后,您可以监听管道drain的{​​{1}}事件以了解它已被完全消耗的时间,无论它是否已写入控制台或数据是否仍在缓存中控制台流。 当然,你也可以自由地忽略这个问题,因为end应该很好地处理完全消耗的流,因此丢弃了,一旦你将它传输到第二个流,你就不用再处理了它。

答案 1 :(得分:1)

创建一个自定义可写内容(如下所示),而不是直接写到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)
  });
  ...
}