Node.js 可写流:write vs _write

Posted

技术标签:

【中文标题】Node.js 可写流:write vs _write【英文标题】:Node.js Writable stream: write vs _write 【发布时间】:2020-08-08 08:06:48 【问题描述】:

我正在阅读 Node.js 官方文档以了解流。我正在实现可写流,但我不明白write_write 之间的区别。

引用this 部分的文档:

在这段时间之间发生的所有对 writable.write() 的调用 writable._write() 被调用并且回调被调用将导致 写入要缓冲的数据。当回调被调用时,流 可能会发出“排水”事件。如果流实现能够 一次处理多个数据块,writable._writev() 方法应该被实现。

这只是让我觉得两者的行为不同,但我不明白如何。

可能是通过在文档中以here 为基础的示例,任何人都可以解释下面给出的代码 sn-ps 在从Readable/Transform 流接收数据时的行为方式有何不同? Readable 流中的 write_write 对应项(如果有)是什么?

const  Writable  = require('stream');

const myWritable = new Writable(
  write(chunk, encoding, callback) 
    if (chunk.toString().indexOf('a') >= 0) 
      callback(new Error('chunk is invalid'));
     else 
      callback();
    
  
);
const  Writable  = require('stream');

class MyWritable extends Writable 
  _write(chunk, encoding, callback) 
    if (chunk.toString().indexOf('a') >= 0) 
      callback(new Error('chunk is invalid'));
     else 
      callback();
    
  

【问题讨论】:

【参考方案1】:

.write() 是可写流的消费者或用户调用以将数据写入流对象的调用。这是任何使用可写流的人都可以使用的公共接口。

._write() 是一个内部接口。它不应该由可写流的消费者或用户调用。它由特定类型的流对象的实现者提供,当需要将数据写入该流背后实际存在的任何存储时,它就会由流本身调用。 它是底层存储的流抽象的一部分。例如,如果您实现了一个表示写入串行端口的流对象,作为该流对象的实现者,您将不得不覆盖泛型_write() 并提供._write() 的实现,只要流基础设施碰巧调用_write(),它就会将字节物理地发送到串行端口。

请注意,在流对象的使用者调用.write() 和流基础设施随后调用._write() 之间没有一对一的对应关系,因为在流对象中进行了缓冲。

此设计还允许您拥有一个通用流接口,该接口下可以有数千种不同的实际存储机制,其中提供._write() 方法是实现存储接口的一部分,以便为其提供通用流接口存储。


并且,在您的第一个代码示例中,将选项对象中的write 属性提供给流构造函数实际上是提供_write() 的实现。构造函数将采用该函数并将其设为_write() 方法。是的,这令人困惑。

在第二个示例中,您直接覆盖了一个方法,因此您必须覆盖 _write() 方法,因为这是实现者必须提供的。

【讨论】:

这是不正确的。有两种方法可以创建Writable。一种方法是扩展类并实现_write 方法。另一种是通过Writable 构造函数,它接受一个选项对象,其中一个是write。在内部,它执行if (options.write) this._write = options.write。 nodejs.org/api/stream.html#stream_simplified_constructiongithub.com/nodejs/node/blob/… @erich2k8 - 是的,你是对的。我已经修改了答案以删除不正确的部分。实际上回答了 OP 关于_write()write() 之间区别的问题的操作部分仍然是正确的。我添加了最后两段以尝试进一步澄清。

以上是关于Node.js 可写流:write vs _write的主要内容,如果未能解决你的问题,请参考以下文章

Node.js 可写流创建错误文件(更大且不可读)

node.js 核心http模块,起一个服务器,返回一个页面

Node.js 全局对象Buffer对象流

Node.js——Stream

管道传输到可写流时暂停可读流

深入node4 可写流的实现 转化流