Maison  >  Article  >  interface Web  >  Une brève discussion sur les flux duplex dans Nodejs

Une brève discussion sur les flux duplex dans Nodejs

青灯夜游
青灯夜游avant
2020-11-23 17:52:343998parcourir

Une brève discussion sur les flux duplex dans Nodejs

Recommandations associées : "Tutoriel node js"

Le flux duplex est un flux qui implémente à la fois les modes lisible et inscriptible, c'est-à-dire vous pouvez En tant que données de production en amont, elles peuvent également être utilisées comme données de consommation en aval, elles peuvent donc se trouver dans la partie centrale du pipeline de flux de données, c'est-à-dire

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

Il existe deux flux duplex couramment utilisés dans NodeJS

  • Duplex

  • Transformer

Duplex

Implémenter Duplex

Similaire aux méthodes d'implémentation de Readable et Writable, il est très simple d'implémenter le flux Duplex, mais Duplex implémente à la fois Readable et Writable ne prend pas en charge l'héritage multiple, donc. nous devons hériter de la classe Duplex

  • Hériter de la classe Duplex

  • implémenter la méthode _read()

  • implémenter la méthode _write()

Je pense que tout le monde connaît l'implémentation des méthodes read() et write(), car elles sont exactement identique à Lisible et Inscriptible.

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

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

Paramètres du constructeur

L'instance Duplex contient des flux lisibles et inscriptibles Plusieurs paramètres peuvent être transmis lors de l'instanciation de la classe Duplex

  • . readableObjectMode : si le flux lisible est défini sur ObjectMode, la valeur par défaut est false
  • writableObjectMode : si le flux inscriptible est défini sur ObjectMode, la valeur par défaut est false
  • allowHalfOpen : La valeur par défaut est true. Si la valeur est false, lorsque la fin de l'écriture se termine, le flux mettra automatiquement fin à la fin de la lecture, et vice versa.

Petit exemple

Après avoir compris Readable et Writable, il est très simple de voir Duplex. Utilisez simplement un exemple du site officiel

 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));
    });
  }
}
Bien sûr, il s'agit d'un pseudo-code qui ne peut pas être exécuté, mais le rôle de Duplex est visible. Il peut produire et consommer des données, il peut donc se trouver au milieu du pipeline de flux de données Common Duplex. are

    Tcp Scoket
  • Zlib
  • Crypto
Transform

Transform est également un flux duplex It. semble être dupliqué avec Duplex, mais les deux Il y a une différence importante : bien que Duplex ait un flux lisible et un flux inscriptible, ils sont relativement indépendants, les données du flux lisible de Transform entreront automatiquement dans le flux inscriptible après un certain traitement ;

Bien qu'il passe d'un flux lisible à un flux inscriptible, cela ne signifie pas que la quantité de données entre les deux est la même. La certaine logique de traitement mentionnée ci-dessus déterminera s'il faut transformer le flux lisible et. puis placez-le dans le flux inscriptible, la signification originale de transform est transformation, qui décrit de manière très appropriée la fonction de flux de Transform.

Notre zlib le plus courant pour la compression et la décompression est le flux de transformation. La quantité de données avant et après la compression et la décompression est évidemment différente. La fonction du flux de transformation est de saisir un package zip et un fichier décompressé ou. vice versa. La plupart des flux duplex que nous utilisons habituellement sont des Transform.

Implémentation de Transform

La classe Transform hérite en interne de Duplex et implémente les méthodes writable.write() et readable._read() Nous souhaitons personnaliser un flux Transform. Il vous suffit de

  • hériter de la classe Transform

  • pour implémenter la méthode _transform()

  • pour implémenter la méthode _flush () (facultatif)

La méthode _transform(chunk, encoding, callback) est utilisée pour recevoir des données et générer une sortie Nous connaissons déjà les paramètres, qui sont. identique à Writable, chunk La valeur par défaut est Buffer, sauf si decodeStrings est défini sur false.

Dans la méthode _transform(), vous pouvez appeler this.push(data) pour produire des données et les transmettre au flux inscriptible, ou vous ne pouvez pas l'appeler, ce qui signifie que l'entrée ne produira pas de sortie.

Lorsque les données sont traitées, callback(err, data) doit être appelé. Le premier paramètre est utilisé pour transmettre les informations d'erreur. Le deuxième paramètre peut être omis. S'il est transmis, l'effet est le même. comme 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);
};
Parfois, l'opération de transformation peut devoir écrire des données supplémentaires dans le flux inscriptible à la fin du flux. Par exemple, les flux Zlib stockent un état interne afin d'optimiser la sortie compressée. Dans ce cas, la méthode _flush() peut être utilisée, qui sera appelée avant que toutes les données écrites ne soient consommées, déclenchant la « fin ».

Événement de transformation

Le flux de transformation a deux événements couramment utilisés

  • terminer à partir de l'écriture

  • se terminer à partir de Lisible

Lorsque transform.end() est appelé et que les données sont traitées par _transform(), finish sera déclenché. Après l'appel de _flush, toutes les données sont sorties et end sera déclenché. . événement.

Comparaison

Après avoir compris Readable et Writable, il est très naturel de comprendre les flux duplex, mais la différence entre les deux va dérouter certains débutants. Une distinction simple : le flux lisible de Duplex et le flux lisible là. Il n'y a pas de relation directe entre les flux d'écriture. Les données du flux lisible dans Transform seront automatiquement placées dans le flux inscriptible après le traitement.

Regardez deux exemples simples pour comprendre intuitivement la différence entre Duplex et Transform

Socket 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。

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

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer