129 votes

Comment fermer un flux lisible (avant la fin) ?

Comment fermer un flux lisible dans Node.js ?

var input = fs.createReadStream('lines.txt');

input.on('data', function(data) {
   // une fois le flux fermé, cette partie du code ne sera
   // plus exécutée

   if (gotFirstLine) {
      // fermer ce flux et continuer les
      // instructions à partir d'ici
      console.log("Fermé.");
   }
});

Ce serait mieux que :

input.on('data', function(data) {
   if (isEnded) { return; }

   if (gotFirstLine) {
      isEnded = true;
      console.log("Fermé.");
   }
});

Mais cela n'arrêterait pas le processus de lecture...

116voto

Yves M. Points 1439

Modifier: Bonne nouvelle ! À partir de Node.js 8.0.0 readable.destroy est officiellement disponible : https://nodejs.org/api/stream.html#stream_readable_destroy_error

ReadStream.destroy

Vous pouvez appeler la fonction ReadStream.destroy à tout moment.

var fs = require("fs");

var readStream = fs.createReadStream("lines.txt");
readStream
    .on("data", function(chunk) {
        console.log(chunk);
        readStream.destroy();
    })
    .on("end", function() {
        // Ceci peut ne pas être appelé puisque nous détruisons le flux
        // la première fois que l'événement "data" est reçu
        console.log("Toutes les données du fichier ont été lues");
    })
    .on("close", function(err) {
        console.log("Le flux a été détruit et le fichier a été fermé");
    });

La fonction publique ReadStream.destroy n'est pas documentée (Node.js v0.12.2) mais vous pouvez consulter le code source sur GitHub (commit du 5 octobre 2012).

La fonction destroy marque internalement l'instance de ReadStream comme détruite et appelle la fonction close pour libérer le fichier.

Vous pouvez écouter l'événement close pour savoir exactement quand le fichier est fermé. L'événement end ne se déclenchera pas sauf si les données sont complètement consommées.


Notez que les fonctions destroy (et close) sont propres à fs.ReadStream. Elles ne font pas partie de l'interface générique stream.readable.

45voto

Nitzan Shaked Points 5333

Appeler input.close(). Ce n'est pas dans la documentation, mais

https://github.com/joyent/node/blob/cfcb1de130867197cbc9c6012b7e84e08e53d032/lib/fs.js#L1597-L1620

fait clairement le travail :) Cela fait en fait quelque chose de similaire à votre isEnded.

MODIFIER 2015-Apr-19 Basé sur les commentaires ci-dessous, et pour clarifier et mettre à jour:

  • Cette suggestion est un hack, et n'est pas documentée.
  • Même en regardant le lib/fs.js actuel cela fonctionne toujours plus d'1,5 ans plus tard.
  • Je suis d'accord avec le commentaire ci-dessous selon lequel appeler destroy() est préférable.
  • Comme correctement indiqué ci-dessous, cela fonctionne pour les ReadStream de fs, pas sur un Readable générique

Pour une solution générique : il ne semble pas y en avoir une, du moins selon ma compréhension de la documentation et d'un rapide coup d'œil à _stream_readable.js.

Ma proposition serait de mettre votre flux lisible en mode en pause, au moins en empêchant un traitement ultérieur de la source de données en amont. N'oubliez pas de unpipe() et de supprimer tous les auditeurs d'événements data pour que pause() fasse effectivement une pause, comme mentionné dans la documentation

27voto

Jo Takion Points 680

Aujourd'hui, dans Node 10

readableStream.destroy()

est la façon officielle de fermer un flux lisible

voir https://nodejs.org/api/stream.html#stream_readable_destroy_error

14voto

thejoshwolfe Points 1790

Vous ne pouvez pas. Il n'existe pas de moyen documenté de fermer/arrêter/interrompre/détruire un flux Readable générique à partir de Node 5.3.0. C'est une limitation de l'architecture des flux de Node.

Comme l'ont expliqué d'autres réponses ici, il existe des astuces non documentées pour des implémentations spécifiques de Readable fournies par Node, telles que fs.ReadStream. Cependant, ce ne sont pas des solutions génériques pour n'importe quel Readable.

Si quelqu'un peut me prouver le contraire, qu'il le fasse. J'aimerais pouvoir faire ce que je dis être impossible, et je serais ravi d'être corrigé.

ÉDITION : Voici ma solution de contournement : implémenter .destroy() pour ma pipeline à travers une série complexe d'appels à unpipe(). Et après toute cette complexité, cela ne fonctionne pas correctement dans tous les cas.

ÉDITION : Node v8.0.0 a ajouté une destroy() api pour les flux Readable.

13voto

Jacob Lowe Points 332

À la version 4.*.*, pousser une valeur nulle dans le flux déclenchera un signal EOF.

À partir de la documentation de nodejs

Si une valeur autre que null est passée, la méthode push() ajoute un morceau de données dans la file d'attente pour que les processeurs de flux ultérieurs puissent le consommer. Si null est passé, cela signale la fin du flux (EOF), après quoi plus aucune donnée ne peut être écrite.

Cela a fonctionné pour moi après avoir essayé de nombreuses autres options sur cette page.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X