Heim  >  Artikel  >  Web-Frontend  >  Eine kurze Diskussion über Duplex-Streams in Nodejs

Eine kurze Diskussion über Duplex-Streams in Nodejs

青灯夜游
青灯夜游nach vorne
2020-11-23 17:52:343998Durchsuche

Eine kurze Diskussion über Duplex-Streams in Nodejs

Verwandte Empfehlungen: „node js-Tutorial

Duplex-Stream ist ein Stream, der gleichzeitig lesbar und beschreibbar ist und als Upstream-Produktionsdaten und Downstream-Verbrauchsdaten verwendet werden kann, sodass dies möglich ist in der Datenflusspipeline Der mittlere Teil, nämlich

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

Es gibt zwei häufig verwendete Duplex-Streams in NodeJS

  • Duplex

  • Transform

Duplex

Implementierung Duplex

und lesbar, Beschreibbare Implementierungsmethode Ebenso ist die Implementierung des Duplex-Streams sehr einfach, aber Duplex implementiert sowohl Readable als auch Writable. NodeJS unterstützt keine Mehrfachvererbung, daher müssen wir die Duplex-Klasse erben

  • Die Duplex-Klasse erben

  • implementieren ()-Methode

  • Implementierung der _write()-Methode

Ich glaube, jeder ist mit der Implementierung der read()- und write()-Methoden vertraut, da sie genau mit Readable und Writable identisch sind.

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

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

Konstruktorparameter

Die Duplex-Instanz enthält sowohl lesbare als auch beschreibbare Streams. Beim Instanziieren der Duplex-Klasse können Sie mehrere Parameter übergeben

  • readableObjectMode: Ob der lesbare Stream auf ObjectMode gesetzt ist, standardmäßig false
  • writableObjectMode: Unabhängig davon, ob der beschreibbare Stream auf ObjectMode eingestellt ist, ist der Standardwert false.
  • allowHalfOpen: Der Standardwert ist true. Wenn er auf false gesetzt ist, beendet der Stream automatisch das Leseende, wenn das Schreiben endet, und umgekehrt Natürlich.

Kleines Beispiel

Nachdem Sie Readable und Writable verstanden haben, ist es sehr einfach, sich Duplex anzusehen. Verwenden Sie einfach ein Beispiel von der offiziellen Website

 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));
    });
  }
}

Natürlich ist dies Pseudocode, der nicht ausgeführt werden kann, aber die Rolle von Duplex ist deutlich zu erkennen und kann Daten erzeugen und Daten verbrauchen, sodass es sich in der Mitte der Datenflusspipeline befinden kann. Zu den gängigen Duplex-Streams gehört

    Zlib
  • Crypto
  • Transform
Transform ist ebenfalls ein Duplex-Stream und sieht aus wie Duplex. Es gibt jedoch einen wichtigen Unterschied zwischen den beiden: Obwohl Duplex über lesbare und beschreibbare Streams verfügt, sind diese relativ unabhängig der beschreibbare Stream nach einem bestimmten Prozess.

Obwohl es von einem lesbaren Stream zu einem beschreibbaren Stream geht, bedeutet dies nicht, dass die Datenmenge zwischen den beiden gleich ist. Die oben erwähnte bestimmte Verarbeitungslogik bestimmt, ob der lesbare Stream umgewandelt und dann eingefügt wird die beschreibbare Stream-Funktion. Es handelt sich um eine Transformation, die die Transform-Flow-Funktion sehr treffend beschreibt.

Unsere gebräuchlichste Zlib für die Komprimierung und Dekomprimierung ist der Transform-Stream. Die Datenmenge vor und nach der Komprimierung und Dekomprimierung ist offensichtlich unterschiedlich. Die Funktion von zlib besteht darin, ein Zip-Paket und eine dekomprimierte Datei einzugeben oder umgekehrt. Die meisten Duplex-Streams, die wir normalerweise verwenden, sind Transform.

Transform implementieren

Die Transform-Klasse erbt intern Duplex und implementiert die Methoden writable.write() und readable._read(). Wenn wir einen Transform-Stream anpassen möchten, müssen wir nur

die Transform-Klasse erben
  • Implementieren Sie die _transform()-Methode
  • Implementieren Sie die _flush()-Methode (optional)
  • _transform(Chunk, Encoding, Callback)-Methode wird verwendet, um Daten zu empfangen und Ausgaben zu generieren. Wir sind bereits damit vertraut Die Parameter sind wie „Writable“ standardmäßig auf „Buffer“ eingestellt, es sei denn, „decodeStrings“ ist auf „false“ gesetzt.
Sie können this.push(data) innerhalb der _transform()-Methode aufrufen, um Daten zu erzeugen und an den beschreibbaren Stream zu übergeben, oder Sie können es nicht aufrufen, was bedeutet, dass die Eingabe keine Ausgabe erzeugt.

Callback(err, data) muss aufgerufen werden, wenn die Daten verarbeitet werden. Der erste Parameter wird zur Übergabe von Fehlerinformationen verwendet. Wenn er übergeben wird, ist der Effekt derselbe wie this.push(. data)

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

transform.prototype._transform = function (data, encoding, callback) {
  callback(null, data);
};
Manchmal muss der Transformationsvorgang am Ende des Streams möglicherweise weitere Daten in den beschreibbaren Stream schreiben. Zlib-Streams speichern beispielsweise einen internen Status, um die komprimierte Ausgabe zu optimieren. In diesem Fall kann die Methode _flush() verwendet werden, die aufgerufen wird, bevor alle geschriebenen Daten verbraucht sind und „Ende“ ausgelöst wird.

Transformationsereignis

Transformationsstrom hat zwei häufig verwendete Ereignisse

Beendet von Beschreibbar
  • Ende von Lesbar
  • Wenn transform.end() aufgerufen wird und die Daten von _transform() verarbeitet werden, wird das Ende beendet Nach dem Aufruf von _flush werden alle Daten ausgegeben und das Endereignis ausgelöst.
Vergleich

Nachdem man den lesbaren und beschreibbaren Stream verstanden hat, ist es ganz natürlich, den Duplex-Stream zu verstehen, aber der Unterschied zwischen den beiden wird einige Anfänger verwirren. Einfache Unterscheidung: Es gibt keine direkte Beziehung zwischen dem lesbaren Stream und dem beschreibbaren Stream im lesbaren Stream in Transform wird nach der Verarbeitung automatisch in den beschreibbaren Stream eingefügt.

Schauen Sie sich zwei einfache Beispiele an, um den Unterschied zwischen Duplex und Transform

TCP-Socket

intuitiv zu verstehen

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。

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

Das obige ist der detaillierte Inhalt vonEine kurze Diskussion über Duplex-Streams in Nodejs. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:cnblogs.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen