Flux Node.js

Découvrez à quoi servent les flux, pourquoi sont-ils si importants et comment les utiliser.

Que sont les flux

Les flux sont l'un des concepts fondamentaux qui alimentent les applications Node.js.

Ils sont un moyen de gérer efficacement la lecture / l'écriture de fichiers, les communications réseau ou tout autre type d'échange d'informations de bout en bout.

Les flux ne sont pas un concept propre à Node.js. Ils ont été introduits dans le système d'exploitation Unix il y a des décennies, et les programmes peuvent interagir les uns avec les autres en passant des flux via l'opérateur de canal (|).

Par exemple, de manière traditionnelle, lorsque vous dites au programme de lire un fichier, le fichier est lu en mémoire, du début à la fin, puis vous le traitez.

En utilisant des flux, vous le lisez morceau par morceau, en traitant son contenu sans tout garder en mémoire.

Le Node.jsstreammodulefournit la base sur laquelle toutes les API de streaming sont construites.

Pourquoi streams

Les flux offrent essentiellement deux avantages majeurs en utilisant d'autres méthodes de traitement des données:

  • Efficacité de la mémoire: vous n'avez pas besoin de charger de grandes quantités de données en mémoire avant de pouvoir les traiter
  • L'efficacité du temps: il faut beaucoup moins de temps pour commencer à traiter les données dès que vous les avez, plutôt que d'attendre que toute la charge utile de données soit disponible pour démarrer

Un exemple de flux

Un exemple typique est celui de la lecture de fichiers à partir d'un disque.

Utilisation du nœudfsmodule, vous pouvez lire un fichier et le servir via HTTP lorsqu'une nouvelle connexion est établie avec votre serveur http:

const http = require('http')
const fs = require('fs')

const server = http.createServer(function (req, res) { fs.readFile(__dirname + ‘/data.txt’, (err, data) => { res.end(data) }) }) server.listen(3000)

readFile()lit le contenu complet du fichier et appelle la fonction de rappel une fois terminé.

res.end(data)dans le rappel retournera le contenu du fichier au client HTTP.

Si le fichier est volumineux, l'opération prendra un peu de temps. Voici la même chose écrite à l'aide de flux:

const http = require('http')
const fs = require('fs')

const server = http.createServer((req, res) => { const stream = fs.createReadStream(__dirname + ‘/data.txt’) stream.pipe(res) }) server.listen(3000)

Au lieu d'attendre que le fichier soit entièrement lu, nous commençons à le diffuser vers le client HTTP dès que nous avons un morceau de données prêt à être envoyé.

tuyau()

L'exemple ci-dessus utilise la lignestream.pipe(res): lepipe()est appelée sur le flux de fichiers.

Que fait ce code? Il prend la source et la dirige vers une destination.

Vous l'appelez sur le flux source, donc dans ce cas, le flux de fichier est redirigé vers la réponse HTTP.

La valeur de retour dupipe()method est le flux de destination, ce qui est très pratique qui nous permet de chaînerpipe()appels, comme ceci:

src.pipe(dest1).pipe(dest2)

Cette construction équivaut à faire

src.pipe(dest1)
dest1.pipe(dest2)

API de nœuds alimentées par Streams

En raison de leurs avantages, de nombreux modules de base Node.js offrent des capacités de gestion de flux natives, notamment:

  • process.stdinrenvoie un flux connecté à stdin
  • process.stdoutrenvoie un flux connecté à stdout
  • process.stderrrenvoie un flux connecté à stderr
  • fs.createReadStream()crée un flux lisible dans un fichier
  • fs.createWriteStream()crée un flux inscriptible dans un fichier
  • net.connect()lance une connexion basée sur le flux
  • http.request()renvoie une instance de la classe http.ClientRequest, qui est un flux accessible en écriture
  • zlib.createGzip()compresser les données à l'aide de gzip (un algorithme de compression) dans un flux
  • zlib.createGunzip()décompressez un flux gzip.
  • zlib.createDeflate()compresser les données à l'aide de deflate (un algorithme de compression) dans un flux
  • zlib.createInflate()décompresser un flux dégonflé

Différents types de flux

Il existe quatre classes de flux:

  • Readable: un flux à partir duquel vous pouvez canaliser, mais pas dans lequel vous pouvez canaliser (vous pouvez recevoir des données, mais pas y envoyer). Lorsque vous envoyez des données dans un flux lisible, elles sont mises en mémoire tampon, jusqu'à ce qu'un consommateur commence à lire les données.
  • Writable: un flux dans lequel vous pouvez canaliser, mais pas depuis (vous pouvez envoyer des données, mais pas en recevoir)
  • Duplex: un flux dans lequel vous pouvez à la fois canaliser et diriger, essentiellement une combinaison d'un flux lisible et inscriptible
  • Transform: un flux de transformation est similaire à un duplex, mais la sortie est une transformation de son entrée

Comment créer un flux lisible

Nous obtenons le flux lisible dustreammodule, et nous l'initialisons

const Stream = require('stream')
const readableStream = new Stream.Readable()

Maintenant que le flux est initialisé, nous pouvons lui envoyer des données:

readableStream.push('hi!')
readableStream.push('ho!')

Comment créer un flux inscriptible

Pour créer un flux inscriptible, nous étendons la baseWritableobject, et nous implémentons sa méthode _write ().

Créez d'abord un objet de flux:

const Stream = require('stream')
const writableStream = new Stream.Writable()

puis implémenter_write:

writableStream._write = (chunk, encoding, next) => {
    console.log(chunk.toString())
    next()
}

Vous pouvez maintenant diriger un flux lisible dans:

process.stdin.pipe(writableStream)

Comment obtenir des données à partir d'un flux lisible

Comment lisons-nous les données d'un flux lisible? Utilisation d'un flux inscriptible:

const Stream = require('stream')

const readableStream = new Stream.Readable() const writableStream = new Stream.Writable()

writableStream._write = (chunk, encoding, next) => { console.log(chunk.toString()) next() }

readableStream.pipe(writableStream)

readableStream.push(‘hi!’) readableStream.push(‘ho!’)

Vous pouvez également consommer un flux lisible directement, en utilisant lereadableun événement:

readableStream.on('readable', () => {
  console.log(readableStream.read())
})

Comment envoyer des données vers un flux inscriptible

Utiliser le fluxwrite()méthode:

writableStream.write('hey!\n')

Signaler un flux inscriptible que vous avez terminé d'écrire

Utilisez leend()méthode:

const Stream = require('stream')

const readableStream = new Stream.Readable() const writableStream = new Stream.Writable()

writableStream._write = (chunk, encoding, next) => { console.log(chunk.toString()) next() }

readableStream.pipe(writableStream)

readableStream.push(‘hi!’) readableStream.push(‘ho!’)

writableStream.end()

Téléchargez mon gratuitManuel de Node.js


Plus de didacticiels sur les nœuds: