【问题标题】:What's the difference between .pipe and pipeline on streams流上的 .pipe 和管道有什么区别
【发布时间】:2020-03-11 12:37:28
【问题描述】:

我在 node.js 中找到了两种不同的管道流方式

众所周知的.pipe()流方法

https://nodejs.org/api/stream.html#stream_readable_pipe_destination_options

流的独立功能

https://nodejs.org/api/stream.html#stream_stream_pipeline_streams_callback

我应该使用哪一个,这两者之间有什么好处?

【问题讨论】:

    标签: node.js stream


    【解决方案1】:

    TL;DR - 你最好使用pipeline

    什么是管道?

    From the docs:一种模块方法,用于在流之间进行管道转发错误并正确清理,并在管道完成时提供回调。

    使用管道的动机是什么?

    ❌ 我们来看看下面的代码:

    const { createReadStream } = require('fs');
    const { createServer } = require('http');
    const server = createServer(
      (req, res) => {
        createReadStream(__filename).pipe(res);
      }
    );
    
    server.listen(3000);
    

    这里有什么问题? 如果响应将退出或客户端关闭连接 - 那么读取流未关闭或销毁,这会导致内存泄漏。

    ✅因此,如果您使用pipeline,它将关闭所有其他流并确保没有内存泄漏。

    const { createReadStream } = require('fs');
    const { createServer } = require('http');
    const { pipeline } = require('stream');
    
    const server = createServer(
      (req, res) => {
        pipeline(
          createReadStream(__filename),
          res,
          err => {
            if (err)
              console.error('Pipeline failed.', err);
            else
              console.log('Pipeline succeeded.');
          }
        );
      }
    );
    
    server.listen(3000);
    

    【讨论】:

      【解决方案2】:

      根据文档,他们都做同样的事情。但也有一些不同:

      • .pipe()Readable 的方法,而pipelinestream 的模块方法,接受流到管道。
      • pipeline() 方法在管道完成时提供回调。
      • pipeline() 方法是从 node 10 版本开始添加的,而.pipe 从最早版本的 node 开始存在。

      在我看来,pipeline() 的代码看起来更简洁一些,但你可以同时使用它们。

      .pipe() 的示例:

      const fs = require('fs');
      const r = fs.createReadStream('file.txt');
      const z = zlib.createGzip();
      const w = fs.createWriteStream('file.txt.gz');
      r.pipe(z).pipe(w);
      

      pipeline() 的例子:

      const { pipeline } = require('stream');
      const fs = require('fs');
      const zlib = require('zlib');
      
      pipeline(
        fs.createReadStream('archive.tar'),
        zlib.createGzip(),
        fs.createWriteStream('archive.tar.gz'),
        (err) => {
          if (err) {
            console.error('Pipeline failed.', err);
          } else {
            console.log('Pipeline succeeded.');
          }
        }
      );
      

      【讨论】:

        【解决方案3】:

        pipelinepipe 的改进版本,它自 Node.js v10 起被添加到流模块

        此外,pipeline 接受任意数量的参数,最后一个参数是一个回调,用于了解管道何时结束或引发错误。

        使用管道:

        mySourceStream.pipe(myStream).pipe(anotherStream)
        

        使用管道:

        mySourceStream.pipeline(myStream, anotherStream, err => {
          if (err) {
            console.log('There is an error')
          } else {
            console.log('pipeline successful')
          }
        })
        

        【讨论】:

          猜你喜欢
          • 2020-03-21
          • 1970-01-01
          • 2020-08-31
          • 2018-08-25
          • 2013-08-09
          • 2021-05-08
          • 2013-09-05
          • 2015-02-02
          相关资源
          最近更新 更多