ホームページ > ウェブフロントエンド > jsチュートリアル > NODE.JS_node.js でストリームを使用するツールを作成する際の注意点

NODE.JS_node.js でストリームを使用するツールを作成する際の注意点

WBOY
リリース: 2016-05-16 15:12:48
オリジナル
1028 人が閲覧しました

Node.js のストリームは非常に強力で、一部のシナリオでは、潜在的に大きなファイルの処理と抽象データの処理と配信をサポートします。非常に使いやすいため、実際の戦闘ではこれをベースにしてツールの関数/ライブラリを作成することがよくありますが、ストリームの特性を無視しているため、作成した関数/ライブラリが要件を満たさない場合があります。 . 望ましい効果、またはいくつかの隠された地雷を敷設します。この記事では、ストリームベースのツールを作成するときに役立つと思われる 2 つのヒントを紹介します。

1. EVENTEMITTER のメモリ リークに注意してください

複数回呼び出される可能性のある関数内で、特定の操作を実行するためにストリームにイベント リスナーを追加する必要がある場合。次に、リスナーの追加によって引き起こされるメモリ リークに注意する必要があります:

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

ログイン後にコピー

上記のコードでは、ストリームがエラーを報告するかデータがない場合、getSomeDataFromStream 関数はエラー イベントと終了イベントをリッスンすることで Promise を完了します。ただし、コードを実行すると、すぐにコンソールにアラーム メッセージが表示されます: (ノード) 警告: EventEmitter メモリ リークの可能性が検出されました。制限を増やすには、emitter.setMaxListeners() を使用してください。この関数が呼び出されるたびに、追加のエラー イベント リスナーと終了イベント リスナーが受信ストリームに追加されます。この潜在的なメモリ リークを回避するには、関数を実行するたびに、この呼び出しによって追加されたすべてのリスナーがクリアされて関数が汚染されないようにする必要があります。

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

ログイン後にコピー

2 番目に、データの処理後にツール関数のコールバックが呼び出されることを確認します

ツール関数は、ストリーム内のすべてのデータが処理された後、コールバック関数パラメーターを外部に提供することがよくあります。通常のアプローチは、ストリームの終了イベントでコールバック関数をハングすることです。ただし、処理される場合 関数は時間のかかる非同期操作であり、すべてのデータが処理される前にコールバック関数が呼び出される場合があります:

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

ログイン後にコピー

ストリームの終了イベントはストリーム内のデータが読み取られたときにのみトリガーされるため、すべてのデータが処理されていないときに上記のコードのコールバックが呼び出される可能性があります。したがって、データが処理されたかどうかをさらに確認する必要があります:

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

ログイン後にコピー

このようにして、すべてのデータが処理された後にコールバックがトリガーされます。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート