Maison > interface Web > js tutoriel > le corps du texte

Points à prendre en compte lors de l'écriture d'outils avec des flux dans NODE.JS_node.js

WBOY
Libérer: 2016-05-16 15:12:48
original
1005 Les gens l'ont consulté

Les flux dans Node.js sont très puissants. Ils prennent en charge le traitement de fichiers potentiellement volumineux ainsi que le traitement et la livraison de données abstraites dans certains scénarios. Parce qu'il est si facile à utiliser, dans les combats réels, nous écrivons souvent des fonctions/bibliothèques d'outils basées sur celui-ci. Cependant, souvent en raison de notre propre négligence de certaines caractéristiques des flux, les fonctions/bibliothèques écrites ne répondront pas aux exigences dans certains cas. . effet souhaité, ou poser des mines cachées. Cet article fournira deux conseils qui me semblent utiles lors de l’écriture d’outils basés sur les flux.

1. Méfiez-vous des fuites de mémoire EVENTEMITTER

Dans une fonction qui peut être appelée plusieurs fois, si vous devez ajouter un écouteur d'événement au flux pour effectuer certaines opérations. Ensuite, vous devez vous méfier des fuites de mémoire provoquées par l'ajout d'écouteurs :

'use strict';
const fs = require('fs');
const co = require('co');

function getSomeDataFromStream (stream) {
 let data = stream.read();
 if (data) return Promise.resolve(data);

 if (!stream.readable) return Promise.resolve(null);

 return new Promise((resolve, reject) => {
  stream.once('readable', () => resolve(stream.read()));
  stream.on('error', reject);
  stream.on('end', resolve);
 })
}

let stream = fs.createReadStream('/Path/to/a/big/file');

co(function *() {
 let chunk;
 while ((chunk = yield getSomeDataFromStream(stream)) !== null) {
  console.log(chunk);
 }
}).catch(console.error);

Copier après la connexion

Dans le code ci-dessus, la fonction getSomeDataFromStream terminera la promesse lorsque le flux signale une erreur ou n'a aucune donnée en écoutant l'événement d'erreur et l'événement de fin. Cependant, lors de l'exécution du code, nous verrons bientôt le message d'alarme dans la console : (nœud) avertissement : possible fuite de mémoire EventEmitter détectée. 11 écouteurs d'erreur ajoutés. Utilisez submitter.setMaxListeners() pour augmenter la limite., car nous sommes dans chaque. Chaque fois que cette fonction est appelée, un écouteur d'événement d'erreur et un écouteur d'événement de fin supplémentaires sont ajoutés au flux entrant. Afin d'éviter cette fuite de mémoire potentielle, nous devons nous assurer qu'après chaque exécution de fonction, tous les écouteurs supplémentaires ajoutés par cet appel sont effacés pour garder la fonction sans pollution :

function getSomeDataFromStream (stream) {
 let data = stream.read();
 if (data) return Promise.resolve(data);

 if (!stream.readable) return Promise.resolve(null);

 return new Promise((resolve, reject) => {
  stream.once('readable', onData);
  stream.on('error', onError);
  stream.on('end', done);

  function onData () {
   done();
   resolve(stream.read());
  }

  function onError (err) {
   done();
   reject(err);
  }

  function done () {
   stream.removeListener('readable', onData);
   stream.removeListener('error', onError);
   stream.removeListener('end', done);
  }
 })
}

Copier après la connexion

Deuxièmement, assurez-vous que le rappel de la fonction outil est appelé après le traitement des données

Les fonctions d'outils fournissent souvent un paramètre de fonction de rappel au monde extérieur. Une fois toutes les données du flux traitées, elles sont déclenchées avec une valeur spécifiée. L'approche habituelle consiste à suspendre la fonction de rappel dans l'événement de fin du flux. , mais si elle est traitée, les fonctions sont des opérations asynchrones qui prennent du temps et les fonctions de rappel peuvent être appelées avant que toutes les données ne soient traitées :

'use strict';
const fs = require('fs');

let stream = fs.createReadStream('/Path/to/a/big/file');

function processSomeData (stream, callback) {
 stream.on('data', (data) => {
  // 对数据进行一些异步耗时操作
  setTimeout(() => console.log(data), 2000);
 });

 stream.on('end', () => {
  // ...
  callback()
 })
}

processSomeData(stream, () => console.log('end'));

Copier après la connexion

Le rappel de code ci-dessus peut être appelé lorsque toutes les données n'ont pas été traitées, car l'événement de fin du flux n'est déclenché que lorsque les données du flux sont lues. Nous devons donc vérifier en plus si les données ont été traitées :

function processSomeData (stream, callback) {
 let count = 0;
 let finished = 0;
 let isEnd = false;

 stream.on('data', (data) => {
  count++;
  // 对数据进行一些异步耗时操作
  setTimeout(() => {
   console.log(data);
   finished++;
   check();
  }, 2000);
 });

 stream.on('end', () => {
  isEnd = true;
  // ...
  check();
 })

 function check () {
  if (count === finished && isEnd) callback()
 }
}

Copier après la connexion

De cette façon, le rappel sera déclenché une fois que toutes les données auront été traitées.

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal