【问题标题】:How to create a Duplex stream in nodejs?如何在 nodejs 中创建双工流?
【发布时间】:2020-03-03 23:35:55
【问题描述】:

我像这样创建一个新的双工流

const Duplex = require('stream').Duplex;
let myStream = new Duplex()

通过 Websocket 我收到块/缓冲区,每次通过 Websocket 有新块进入时,我都会像这样将其添加到流中:

myStream.push(buffer)

然后我将流传输到另一个进程(本例中为 ffmpeg)

myStream.pipe(process.stdout); 这会导致错误NodeError: The _read() method is not implemented 我理解但我不明白为什么以及如何实现它。我还看到,在 Duplex 类构造函数中,您可以传递一个读取函数,但为什么这是必要的?我只想不断将块推送到流中,然后将其通过管道传输到另一个进程

【问题讨论】:

    标签: javascript node.js stream


    【解决方案1】:

    nodejs Duplex 流要求实现者同时指定写入和读取方法:

    import stream from 'stream';
    
    const duplex = new stream.Duplex({
      write: (chunk, encoding, next) {
        // Do something with the chunk and then call next() to indicate 
        // that the chunk has been processed. The write() fn will handle
        // data piped into this duplex stream. After the write() has
        // finished, the data will be processed by the read() below.
        next();
      },
      read: ( size ) {
        // Add new data to be read by streams piped from this duplex
        this.push( "some data" )
      }
    })
    

    有关流的官方 nodejs 文档可在此处获得:API for Stream Implementers

    websocket 场景
    上面描述的 websocket 示例可能应该使用 Readable 而不是双工流。双工流在存储转发或处理转发场景中很有用。但是,听起来 websocket 示例中的流仅用于将数据从 websocket 移动到流接口。这可以使用 Readable 来实现:

    
    import stream from 'stream';
    
    const onSocketConnection = ( socket ) => {
        const readable = new stream.Readable({
          // The read logic is omitted since the data is pushed to the socket
          // outside of the script's control. However, the read() function 
          // must be defined.
          read(){}
        });
    
        socket.on('message', ( data ) => {
            // Push the data on the readable queue
            readable.push( data );
        });
    
        readable.pipe( ffmpeg );
    }
    

    【讨论】:

    • 我明白了,谢谢你的解释!但我仍然想知道为什么你应该在 read() 中 push 。此外,当您连续写入(推送)到可读流时,感觉就像是可读 + 可写。那与双工有什么不同呢?我不知道为什么我的示例代码使用双工流,但它只是将流传输到sox,然后传输到ffmpeg,但如果我使用行为像你描述的Readable,我猜应该可以正常工作跨度>
    • 执行push 意味着通过管道发送数据,同时在您的可读信号上调用其他组件read 表明相应的数据接收器已准备好接收更多数据。我认为,在这种情况下,为什么可读是正确选择的最简单原因是,您不希望双工会引入两个缓冲区(写入和读取) - 只有读取缓冲区是必要的(其中是推送数据的去向)。就个人而言,我只是在使用流 API 一段时间后才对何时使用双工/转换以及何时使用其他东西感到满意。
    • 好的,所以我理解我的流是Readable 是正确的,因为“其他人”通过.pipe 从它读取但它不可写,因为我定义自己如何填充读取缓冲区(通过可读.push)?我的困惑在于命名,因为我首先认为“读取”函数读取进入流中的数据 - 事实并非如此,因为它是当有人想要从中获取数据时调用的函数。但是在某种程度上,我的可读流有点“可写”,因为我从外部执行了自定义 push,对吗?我在流中写了一些东西——这让我很困惑!
    • 是的!说得好。我最初以同样的方式误解了文档:)
    猜你喜欢
    • 2013-10-24
    • 2019-03-18
    • 2022-10-07
    • 1970-01-01
    • 2011-02-23
    • 1970-01-01
    • 1970-01-01
    • 2016-07-30
    • 2012-02-14
    相关资源
    最近更新 更多