Heim > Web-Frontend > js-Tutorial > Worauf Sie beim Schreiben von Tools mit Streams in NODE.JS_node.js achten sollten

Worauf Sie beim Schreiben von Tools mit Streams in NODE.JS_node.js achten sollten

WBOY
Freigeben: 2016-05-16 15:12:48
Original
1031 Leute haben es durchsucht

Streams in Node.js sind sehr leistungsfähig. Sie bieten in einigen Szenarien Unterstützung für die Verarbeitung potenziell großer Dateien und die Verarbeitung und Bereitstellung abstrakter Daten. Da es so einfach zu verwenden ist, schreiben wir im tatsächlichen Kampf häufig einige darauf basierende Toolfunktionen/Bibliotheken. Aufgrund unserer eigenen Vernachlässigung bestimmter Stream-Eigenschaften erfüllen die geschriebenen Funktionen/Bibliotheken jedoch in einigen Fällen nicht die Anforderungen . gewünschte Wirkung, oder legen Sie einige versteckte Minen. Dieser Artikel enthält zwei Tipps, die meiner Meinung nach beim Schreiben streambasierter Tools nützlich sind.

1. Seien Sie vorsichtig bei EVENTEMITTER-Speicherlecks

In einer Funktion, die mehrmals aufgerufen werden kann, wenn Sie dem Stream einen Ereignis-Listener hinzufügen müssen, um bestimmte Vorgänge auszuführen. Dann müssen Sie sich vor Speicherverlusten in Acht nehmen, die durch das Hinzufügen von Listenern verursacht werden:

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

Nach dem Login kopieren

Im obigen Code vervollständigt die Funktion getSomeDataFromStream das Promise, wenn der Stream einen Fehler meldet oder keine Daten hat, indem sie das Fehlerereignis und das Endereignis abhört. Beim Ausführen des Codes wird jedoch bald die Alarmmeldung in der Konsole angezeigt: (Knoten) Warnung: Möglicher EventEmitter-Speicherverlust. 11 Fehler-Listener hinzugefügt, um das Limit zu erhöhen., da wir uns in jedem befinden Bei jedem Aufruf dieser Funktion werden dem eingehenden Stream ein zusätzlicher Fehlerereignis-Listener und ein Endereignis-Listener hinzugefügt. Um diesen potenziellen Speicherverlust zu vermeiden, müssen wir sicherstellen, dass nach jeder Funktionsausführung alle durch diesen Aufruf hinzugefügten zusätzlichen Listener gelöscht werden, um die Funktion verschmutzungsfrei zu halten:

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

Nach dem Login kopieren

Zweitens stellen Sie sicher, dass der Rückruf der Tool-Funktion nach der Verarbeitung der Daten aufgerufen wird

Tool-Funktionen stellen der Außenwelt häufig einen Callback-Funktionsparameter zur Verfügung. Nachdem alle Daten im Stream verarbeitet wurden, wird er mit einem angegebenen Wert ausgelöst. Der übliche Ansatz besteht darin, die Callback-Funktion am Ende des Streams aufzuhängen , aber wenn es verarbeitet wird, sind Funktionen zeitaufwändige asynchrone Vorgänge und Rückruffunktionen können aufgerufen werden, bevor alle Daten verarbeitet sind:

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

Nach dem Login kopieren

Der obige Code-Rückruf kann aufgerufen werden, wenn nicht alle Daten verarbeitet wurden, da das Endereignis des Streams nur ausgelöst wird, wenn die Daten im Stream gelesen werden. Daher müssen wir zusätzlich prüfen, ob die Daten verarbeitet wurden:

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

Nach dem Login kopieren

Auf diese Weise wird der Rückruf ausgelöst, nachdem alle Daten verarbeitet wurden.

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage