NodeJS 中 response.write 与 stream.pipe(response) 的区别

Difference between response.write vs stream.pipe(response) in NodeJS

据我了解,"response.write" 可以更好地控制我正在写入的数据块,而 pipe 对数据块没有任何控制权。

我正在尝试流式传输文件,我不需要对数据块进行任何控制,因此建议使用 stream.pipe(response) 吗?与 response.write 相比,性能有什么优势吗?

 downloadStream = readBucket.openDownloadStream(trackID)
 downloadStream.on('data', chunk => {
      console.log('chunk');
      res.write(chunk);
    });

    downloadStream.on('error', error => {
      console.log('error occured', error)
      res.sendStatus(500);
    });

    downloadStream.on('end', () => {
      res.end();
    });

对于我的场景,两个代码的作用相同。我更喜欢管道,因为代码更少。与 response.write 相比,pipe() 是否有任何性能优势,memory/io 效率优势?

downloadStream= readBucket.openDownloadStream(trackID)
      downloadStream.pipe(res);

.pipe() 只是一种将读取流发送到写入流的现成方法。如果需要,您当然可以手动编写代码,但是 .pipe() 可以为您处理很多事情。

我建议它有点像 fs.readFile()。如果你想做的是将整个文件读入内存,fs.readFile() 会完成打开文件进行读取、将所有数据读入缓冲区、关闭目标文件并在最后给你所有数据的工作.如果有任何错误,它会确保您正在阅读的文件已关闭。

.pipe()也是如此。它为您连接到 datafinisherror 事件并处理所有这些事件,同时将数据流式传输到我们的写入流。根据写入流的类型,它还会处理 "finishing" 或 "closing" 读取流和写入流,即使存在错误也是如此。

而且,.pipe() 具有回流处理功能,这是您的代码所没有的。当您调用 res.write() 时,它 returns 是一个布尔值。如果该布尔值是 true,则写入缓冲区已满,您不应再次调用 res.write(),直到 drain 事件发生。请注意,您的代码不会这样做。因此,.pipe() 比许多人通常自己写的内容更完整。

我见过的唯一情况是您通常在执行类似管道的操作,但您不能使用 .pipe() 是在错误情况下您有非常自定义的行为并且您想要执行与默认错误处理明显不同的东西。对于只是流式传输数据并完成输入和输出流,在错误时终止两者,它完全符合您的要求,因此当所需的行为已经内置时,真的没有理由自己编写代码。

For my scenario, both codes do the same. I prefer pipe because of less code.

这里也一样。

Is there any performance benefits, memory/io efficiency advantages with pipe() over response.write?

是的,有点。它可能比你自己写的代码有更少的错误(比如在你的例子中忘记了回流检测,它可能只出现在某些情况下,大数据,慢速连接)。