stream 模块 API 旨在为了更容易地使用 JavaScript 的原型继承模式来实现流。

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

    1. const { Writable } = require('stream');
    2. class MyWritable extends Writable {
    3. constructor({ highWaterMark, ...options }) {
    4. super({ highWaterMark });
    5. // ...
    6. }
    7. }

    当继承流时,在传入基本构造函数之前,务必清楚使用者可以且应该提供哪些选项。 例如,如果实现需要 autoDestroyemitClose 选项,则不允许使用者覆盖这些选项。 应明确要传入的选项,而不是隐式地传入所有选项。

    新的流类必须实现一个或多个特定的方法,具体取决于要创建的流的类型,如下图所示:

    用例 需要实现的方法
    只读 [Readable] [_read()][stream-_read]
    只写 [Writable] [_write()][stream-_write]、[_writev()][stream-_writev]、[_final()][stream-_final]
    可读可写 [Duplex] [_read()][stream-_read]、[_write()][stream-_write]、[_writev()][stream-_writev]、[_final()][stream-_final]
    对写入的数据进行操作,然后读取结果 [Transform][] [_transform()][stream-_transform]、[_flush()][stream-_flush]、[_final()][stream-_final]

    流的实现代码应永远不要调用旨在供消费者使用的公共方法(详见[用于消费流的API][API for Stream Consumers])。 这样做可能会导致消费流的应用程序代码产生不利的副作用。

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