Node.js PassThrough 流没有正确关闭?

fou*_*r43 5 node.js node.js-stream

我很好奇我的 PassThrough 流以及为什么在我通过管道将其关闭的资源后它没有关闭。我将它用作中介,一个资源需要一个 ReadableStream,我需要向用户传递一个 WriteableStream 以允许他们编写底层资源。起初,双工流看起来很理想,但需要一些实现,然后我找到了 PassThrough 流。

编辑:这里问题的最佳描述:https : //gist.github.com/four43/46fd38fd0c929b14deb6f1744b63026a

原始示例: 看看这个:

const fs = require('fs');
const stream = require('stream');

const passThrough = new stream.PassThrough({allowHalfOpen: false});
const writeStream = new fs.createWriteStream('/tmp/output.txt');

passThrough.pipe(writeStream)
    .on('end', () => console.log('full-end'))
    .on('close', () => console.log('full-close'))
    .on('unpipe', () => console.log('full-unpipe'))
    .on('finish', () => console.log('full-finish'));
passThrough
    .on('end', () => console.log('passThrough-end'))
    .on('close', () => console.log('passThrough-close'))
    .on('unpipe', () => console.log('passThrough-unpipe'))
    .on('finish', () => console.log('passThrough-finish'));

passThrough.end('hello world');
Run Code Online (Sandbox Code Playgroud)

实际输出:

passThrough-finish
passThrough-end
full-unpipe
full-finish
full-close
Run Code Online (Sandbox Code Playgroud)

似乎写端完成了它的工作,但 PassThrough 流的“读取”端不会传播关闭,即使“allowHalfOpen”选项被传递为 false(我可以验证调试器中的选项)。

我在这一切都错了吗?我将如何传播 writeStream 的关闭?

谢谢。

编辑:我发现变换流也是如此,它们只是管道关闭的末端锥体。有没有办法手动关闭它们?transform.end() 永远不会导致流抛出“关闭”事件,只是在底层资源成功之前触发的“完成”和“结束”事件。

Edit2:我把这个要点放在一起:https : //gist.github.com/four43/46fd38fd0c929b14deb6f1744b63026a

这表明当可写完成时, readable.pipe(writable) 中的可读被正确关闭。这会让我相信,当我执行 transform.pipe(writable) 时,它会关闭转换流的“可读”端,因为我已经用 .end() “关闭”了可写端,它应该关闭整个溪流。有趣的旁注:即使我们在测试 2 中从未使用过 read,它也会抛出事件。可能是一个隔离问题,但我认为我的超时等待做得很好。

pet*_*teb 1

如果您想知道何时writeStream完成写入,那么只需监听'finish'事件即可writeStream

const fs = require('fs');
const stream = require('stream');

const passThrough = new stream.PassThrough({allowHalfOpen: false});
const writeStream = new fs.createWriteStream('/tmp/output.txt');

passThrough
    .on('error', (err) => console.error(err))
    .on('end', () => console.log('passThrough-end'))
    .on('close', () => console.log('passThrough-close'))
    .on('unpipe', () => console.log('passThrough-unpipe'))
    .on('finish', () => console.log('passThrough-finish'));

writeStream
    .on('error', (err) => console.error(err))
    .on('close', () => console.log('full-close'))
    .on('unpipe', () => console.log('full-unpipe'))
    .on('finish', () => console.log('full-finish'));

// passThrough-finish written because all Writes are complete
passThrough.end('hello world');

passThrough.pipe(writeStream);
Run Code Online (Sandbox Code Playgroud)

  • 为了保证底层流的内容已经完成写入,需要等待写入流完成。如果你不小心的话,你会遇到各种奇怪的问题。这实际上是因为失败的单元测试正在寻找完成写入流、读取文件的内容,而不是在那里。 (3认同)