ホームページ  >  記事  >  ウェブフロントエンド  >  Nodejs の二重ストリームについての簡単な説明

Nodejs の二重ストリームについての簡単な説明

青灯夜游
青灯夜游転載
2020-11-23 17:52:344056ブラウズ

Nodejs の二重ストリームについての簡単な説明

関連する推奨事項: 「node js チュートリアル

二重ストリームは、読み取り可能と書き込み可能の両方を実装するストリームです。アップストリームの実稼働データとしてだけでなく、ダウンストリームの消費データとしても使用できるため、データ フロー パイプラインの中間部分、つまり

 rs.pipe(rws1).pipe(rws2).pipe(rws3).pipe(ws);

には一般的に使用される 2 つの二重ストリームがあります。 NodeJS

  • Duplex

  • Transform

Duplex

Duplex の実装

Readable および Writable の実装方法と同様に、Duplex ストリームの実装は非常に簡単ですが、Duplex は Readable と Writable の両方を実装します。NodeJS は多重継承をサポートしていないため、 Duplex クラスを継承する必要があります

  • Duplex クラスを継承します

  • _read() メソッドを実装します

  • _write() メソッドを実装する

誰もが read() メソッドと write() メソッドの実装に精通していると思います。読み取り可能および書き込み可能と同じです。

const Duplex = require('stream').Duplex;

const myDuplex = new Duplex({
  read(size) {
    // ...
  },
  write(chunk, encoding, callback) {
    // ...
  }
});

コンストラクター パラメーター

Duplex インスタンスには読み取り可能なストリームと書き込み可能なストリームの両方が含まれています。Duplex クラスをインスタンス化するときにいくつかのパラメーターを渡すことができます

  • readableObjectMode: 読み取り可能なストリームが ObjectMode に設定されているかどうか、デフォルトは false
  • writableObjectMode: 書き込み可能なストリームが ObjectMode に設定されているかどうか、デフォルトは false
  • allowHalfOpen: デフォルトは true です。false に設定すると、書き込み終了時にストリームは自動的に読み取り終了となり、その逆も同様です。

小さな例

Readable と Writable を理解すると、Duplex を確認するのは非常に簡単です。公式 Web サイトの例を使用してください

 const Duplex = require('stream').Duplex;
const kSource = Symbol('source');

class MyDuplex extends Duplex {
  constructor(source, options) {
    super(options);
    this[kSource] = source;
  }

  _write(chunk, encoding, callback) {
    // The underlying source only deals with strings
    if (Buffer.isBuffer(chunk))
      chunk = chunk.toString();
    this[kSource].writeSomeData(chunk);
    callback();
  }

  _read(size) {
    this[kSource].fetchSomeData(size, (data, encoding) => {
      this.push(Buffer.from(data, encoding));
    });
  }
}

もちろん、これは実行できない疑似コードですが、Duplex の役割がわかります。データを生成したり消費したりできるため、データ フロー パイプラインの途中に置くことができます。一般的な Duplex フロー

    #Tcp Scoket
  • Zlib
  • Crypto
Transform

Transform も二重ストリームです。 Duplex と重複しているように見えますが、両方とも重要な違いがあります。Duplex には読み取り可能なストリームと書き込み可能なストリームがありますが、それらは比較的独立しています。Transform の読み取り可能なストリーム内のデータは、特定の処理後に自動的に書き込み可能なストリームに入ります。

読み取り可能なストリームから書き込み可能なストリームに入りますが、両者のデータ量が同じであるわけではなく、上記の特定の処理ロジックにより読み取り可能なストリームを変換するかどうかが決定され、その後、それを書き込み可能なストリームに入れます。transform の本来の意味は変換であり、Transform フロー関数を非常に適切に説明しています。

圧縮と解凍用の最も一般的な zlib は、変換ストリームです。圧縮と解凍の前後でデータ量は明らかに異なります。変換ストリームの機能は、zip パッケージと解凍されたファイル、または逆に。私たちが通常使用する二重ストリームのほとんどは Transform です。

Tranform の実装

Tranform クラスは内部的に Duplex を継承し、writable.write() メソッドと readable._read() メソッドを実装します。Transform ストリームをカスタマイズしたいと考えています。

  • Transform クラスを継承します

  • _transform() メソッドを実装します

  • implement _flush ( ) メソッド (オプション)

_transform(chunk, encoding, callback) メソッドは、データを受信して​​出力を生成するために使用されます。パラメーターについては、Writable と同じであるため、すでによく理解しています。 chunk decodeStrings が false に設定されていない限り、デフォルトは Buffer です。

_transform() メソッド内で this.push(data) を呼び出してデータを生成し、書き込み可能なストリームに渡すこともできますが、呼び出すことはできません。つまり、入力から出力が生成されません。

データが処理されるとき、callback(err, data) を呼び出す必要があります。最初のパラメータは、エラー情報を渡すために使用されます。2 番目のパラメータは省略できます。渡された場合、効果は同じですas this.push(data) Same

 transform.prototype._transform = function (data, encoding, callback) {
  this.push(data);
  callback();
};

transform.prototype._transform = function (data, encoding, callback) {
  callback(null, data);
};
場合によっては、変換操作でストリームの最後にある書き込み可能なストリームにさらにデータを書き込む必要がある場合があります。たとえば、Zlib ストリームは、圧縮出力を最適化するためにいくつかの内部状態を保存します。この場合、_flush() メソッドを使用できます。このメソッドは、書き込まれたすべてのデータが消費される前に呼び出され、「終了」をトリガーします。

Transform イベント

Transform ストリームには一般的に使用される 2 つのイベントがあります

  • finish from Writable

  • end from Readable

transform.end() が呼び出され、データが _transform() によって処理されると、finish がトリガーされます。_flush が呼び出された後、すべてのデータが出力され、end が実行されます。トリガーされたイベント。

比較

Readable と Writable を理解した後、duplex ストリームを理解するのは非常に自然ですが、初心者の中には 2 つの違いがあるため混乱する人もいます。書き込みストリーム間に直接の関係はありません。Transform の読み取り可能ストリーム内のデータは、処理後に自動的に書き込み可能ストリームに入れられます。

Duplex と Transform の違いは、2 つの簡単な例を見ることで直感的に理解できます。

TCP ソケット

net 模块可以用来创建 socket,socket 在 NodeJS 中是一个典型的 Duplex,看一个 TCP 客户端的例子

var net = require('net');

//创建客户端
var client = net.connect({port: 1234}, function() {
    console.log('已连接到服务器');
    client.write('Hi!');
});

//data事件监听。收到数据后,断开连接
client.on('data', function(data) {
    console.log(data.toString());
    client.end();
});

//end事件监听,断开连接时会被触发
client.on('end', function() {
    console.log('已与服务器断开连接');
});

可以看到 client 就是一个 Duplex,可写流用于向服务器发送消息,可读流用于接受服务器消息,两个流内的数据并没有直接的关系。

gulp

gulp 非常擅长处理代码本地构建流程,看一段官网的示例代码

gulp.src('client/templates/*.jade')
  .pipe(jade())
  .pipe(minify())
  .pipe(gulp.dest('build/minified_templates'));

其中 jada() 和 minify() 就是典型的 Transform,处理流程大概是

.jade 模板文件 -> jada() -> html 文件 -> minify -> 压缩后的 html

可以看出来,jade() 和 minify() 都是对输入数据做了些特殊处理,然后交给了输出数据。

这样简单的对比就能看出 Duplex 和 Transform 的区别,在平时实用的时候,当一个流同事面向生产者和消费者服务的时候我们会选择 Duplex,当只是对数据做一些转换工作的时候我们便会选择使用 Tranform。

更多编程相关知识,请访问:编程学习网站!!

以上がNodejs の二重ストリームについての簡単な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はcnblogs.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。