ホームページ  >  記事  >  ウェブフロントエンド  >  Node.js ストリームについて: 何を、なぜ、どのように使用するのか

Node.js ストリームについて: 何を、なぜ、どのように使用するのか

Mary-Kate Olsen
Mary-Kate Olsenオリジナル
2024-09-21 06:24:08339ブラウズ

Understanding Node.js Streams: What, Why, and How to Use Them

Node.js ストリームは、大量のデータを効率的に処理するために不可欠な機能です。従来の入出力メカニズムとは異なり、ストリームを使用すると、データ全体をメモリにロードするのではなく、データをチャンク単位で処理できるため、大きなファイルやリアルタイム データの処理に最適です。この記事では、Node.js ストリームとは何か、それが役立つ理由、実装方法、さまざまな種類のストリームについて、詳細な例と使用例を交えて詳しく説明します。

Node.js ストリームとは何ですか?

簡単に言うと、ストリームとは、時間の経過とともにあるポイントから別のポイントに移動される一連のデータです。データが一度に流れるのではなく、少しずつ流れるベルトコンベアと考えることができます。

Node.js ストリームも同様に機能します。データを (一度にすべてではなく) 分割して読み書きできるため、メモリ効率が高くなります。

Node.js のストリームは EventEmitter の上に構築され、イベント駆動型になります。いくつかの重要なイベントは次のとおりです:

  • data: データが利用可能な場合に発行されます。
  • end: 消費できるデータがなくなったときに発行されます。
  • error: 読み取りまたは書き込み中にエラーが発生した場合に発行されます。

ストリームを使用する理由

ストリームには、I/O を処理するための fs.readFile() や fs.writeFile() などの従来のメソッドに比べて、いくつかの利点があります。

  1. メモリ効率: データはチャンク単位で処理されるため、大量のメモリを消費せずに非常に大きなファイルを処理できます。
  2. パフォーマンス: ストリームはノンブロッキング I/O を提供します。これらにより、操作全体が完了するのを待たずにデータを部分的に読み書きできるため、プログラムの応答性が向上します。
  3. リアルタイム データ処理: ストリームにより、ライブ ビデオ/オーディオや API からの大規模なデータセットなどのリアルタイム データの処理が可能になります。

Node.js のストリームの種類

Node.js には 4 種類のストリームがあります:

  1. 読み取り可能なストリーム: データの読み取り用。
  2. 書き込み可能なストリーム: データの書き込み用。
  3. 二重ストリーム: データの読み取りと書き込みを同時に実行できるストリーム。
  4. 変換ストリーム: 出力が入力の修正バージョンである二重ストリームのタイプ (データ圧縮など)。

各タイプを例を挙げて見てみましょう。

1. 読み取り可能なストリーム

読み取り可能なストリームは、データをチャンクごとに読み取るために使用されます。たとえば、大きなファイルを読み取る場合、読み取り可能なストリームを使用すると、ファイル全体を読み込むのではなく、データの小さな塊をメモリに読み取ることができます。

例: Readable Stream を使用したファイルの読み取り

const fs = require('fs');

// Create a readable stream
const readableStream = fs.createReadStream('largefile.txt', { encoding: 'utf8' });

// Listen for data events and process chunks
readableStream.on('data', (chunk) => {
  console.log('Chunk received:', chunk);
});

// Listen for the end event when no more data is available
readableStream.on('end', () => {
  console.log('No more data.');
});

// Handle error event
readableStream.on('error', (err) => {
  console.error('Error reading the file:', err);
});

説明:

  • fs.createReadStream() は、ファイルをチャンクで読み取るストリームを作成します。
  • データ イベントはチャンクの準備ができるたびにトリガーされ、読み取るデータがなくなると終了イベントがトリガーされます。

2. 書き込み可能なストリーム

書き込み可能なストリームは、データをチャンクごとに書き込むために使用されます。すべてのデータを一度に書き込む代わりに、ファイルまたは別の書き込み可能な宛先にストリーミングできます。

例: 書き込み可能ストリームを使用したデータの書き込み

const fs = require('fs');

// Create a writable stream
const writableStream = fs.createWriteStream('output.txt');

// Write chunks to the writable stream
writableStream.write('Hello, World!\n');
writableStream.write('Streaming data...\n');

// End the stream (important to avoid hanging the process)
writableStream.end('Done writing.\n');

// Listen for the finish event
writableStream.on('finish', () => {
  console.log('Data has been written to output.txt');
});

// Handle error event
writableStream.on('error', (err) => {
  console.error('Error writing to the file:', err);
});

説明:

  • fs.createWriteStream() は書き込み可能なストリームを作成します。
  • データは write() メソッドを使用してストリームに書き込まれます。
  • すべてのデータが書き込まれると終了イベントがトリガーされ、end() メソッドがストリームの終了をマークします。

3. 二重ストリーム

二重ストリームはデータの読み取りと書き込みの両方ができます。二重ストリームの典型的な例は、データを同時に送受信できるネットワーク ソケットです。

例: 二重ストリーム

const { Duplex } = require('stream');

const duplexStream = new Duplex({
  write(chunk, encoding, callback) {
    console.log(`Writing: ${chunk.toString()}`);
    callback();
  },
  read(size) {
    this.push('More data');
    this.push(null);  // End the stream
  }
});

// Write to the duplex stream
duplexStream.write('Hello Duplex!\n');

// Read from the duplex stream
duplexStream.on('data', (chunk) => {
  console.log(`Read: ${chunk}`);
});

説明:

  • 書き込み用の write メソッドと読み取り用の read メソッドを定義します。
  • 二重ストリームは、読み取りと書き込みの両方を同時に処理できます。

4. ストリームの変換

変換ストリームは、ストリームを通過するときにデータを変更します。たとえば、変換ストリームはデータを圧縮、暗号化、または操作できます。

例: 変換ストリーム (テキストの大文字化)

const { Transform } = require('stream');

// Create a transform stream that converts data to uppercase
const transformStream = new Transform({
  transform(chunk, encoding, callback) {
    this.push(chunk.toString().toUpperCase());
    callback();
  }
});

// Pipe input to transform stream and then output the result
process.stdin.pipe(transformStream).pipe(process.stdout);

説明:

  • stdin から入力されたデータは、transform メソッドによって大文字に変換され、stdout に出力されます。

配管ストリーム

Node.js ストリームの重要な機能の 1 つは、パイプ処理できることです。パイピングを使用すると、ストリームを連鎖させて、あるストリームの出力を入力として別のストリームに渡すことができます。

例: 読み取り可能なストリームを書き込み可能なストリームにパイプする

const fs = require('fs');

// Create a readable stream for the input file
const readableStream = fs.createReadStream('input.txt');

// Create a writable stream for the output file
const writableStream = fs.createWriteStream('output.txt');

// Pipe the readable stream into the writable stream
readableStream.pipe(writableStream);

// Handle errors
readableStream.on('error', (err) => console.error('Read error:', err));
writableStream.on('error', (err) => console.error('Write error:', err));

説明:

  • pipe() メソッドは、読み取り可能なストリームを書き込み可能なストリームに接続し、データ チャンクを input.txt から output.txt に直接送信します。

Node.js ストリームの実用的な使用例

  1. 大きなファイルの読み取りと書き込み: ファイル全体をメモリに読み取る代わりに、ストリームを使用すると、ファイルを小さな塊で処理できます。
  2. リアルタイム データ処理: ストリームは、オーディオ/ビデオ処理、チャット アプリケーション、ライブ データ フィードなどのリアルタイム アプリケーションに最適です。
  3. HTTP リクエスト/レスポンス: Node.js の HTTP リクエストとレスポンスはストリームであるため、受信データの処理やデータの段階的な送信が簡単になります。

結論

Node.js ストリームは、チャンク内のデータを操作することで I/O 操作を処理する強力かつ効率的な方法を提供します。大きなファイルを読み取る場合でも、ソース間でデータをパイプする場合でも、オンザフライでデータを変換する場合でも、ストリームはメモリ効率が高くパフォーマンスの高いソリューションを提供します。アプリケーションで読み取り可能、書き込み可能、​​二重、および変換ストリームを活用する方法を理解すると、アプリケーションのパフォーマンスとスケーラビリティを大幅に向上させることができます。

以上がNode.js ストリームについて: 何を、なぜ、どのように使用するのかの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。