流实现者的 API


【API for stream implementers】

node:stream 模块 API 的设计目的是使得可以轻松地使用 JavaScript 的原型继承模型来实现流。

【The node:stream module API has been designed to make it possible to easily implement streams using JavaScript's prototypal inheritance model.】

首先,流开发者会声明一个新的 JavaScript 类,该类继承四个基本流类之一(stream.Writablestream.Readablestream.Duplexstream.Transform),并确保调用相应的父类构造函数:

【First, a stream developer would declare a new JavaScript class that extends one of the four basic stream classes (stream.Writable, stream.Readable, stream.Duplex, or stream.Transform), making sure they call the appropriate parent class constructor:】

const { Writable } = require('node:stream');

class MyWritable extends Writable {
  constructor({ highWaterMark, ...options }) {
    super({ highWaterMark });
    // ...
  }
} 

在扩展流时,请记住用户可以并且应该在将这些选项传递给基础构造函数之前提供哪些选项。例如,如果实现对 autoDestroyemitClose 选项做出了假设,不要允许用户覆盖这些选项。要明确哪些选项会被转发,而不是隐式地转发所有选项。

【When extending streams, keep in mind what options the user can and should provide before forwarding these to the base constructor. For example, if the implementation makes assumptions in regard to the autoDestroy and emitClose options, do not allow the user to override these. Be explicit about what options are forwarded instead of implicitly forwarding all options.】

新的流类必须根据所创建的流类型实现一个或多个特定方法,如下表所示:

【The new stream class must then implement one or more specific methods, depending on the type of stream being created, as detailed in the chart below:】

用例需要实现的方法
仅读取Readable_read()
仅写入Writable_write(), _writev(), _final()
读写Duplex_read(), _write(), _writev(), _final()
操作已写入的数据,然后读取结果Transform_transform(), _flush(), _final()

流的实现代码绝不应调用供消费者使用的流的“公共”方法(如 流消费者的 API 节所述)。这样做可能会导致使用该流的应用代码出现不良副作用。

【The implementation code for a stream should never call the "public" methods of a stream that are intended for use by consumers (as described in the API for stream consumers section). Doing so may lead to adverse side effects in application code consuming the stream.】

避免重写公共方法,例如 write()end()cork()uncork()read()destroy(),或通过 .emit() 触发内部事件,例如 'error''data''end''finish''close'。这样做可能会破坏当前和未来的流不变量,导致与其他流、流工具以及用户预期之间的行为和/或兼容性问题。

【Avoid overriding public methods such as write(), end(), cork(), uncork(), read() and destroy(), or emitting internal events such as 'error', 'data', 'end', 'finish' and 'close' through .emit(). Doing so can break current and future stream invariants leading to behavior and/or compatibility issues with other streams, stream utilities, and user expectations.】