この記事では、Nodejs のストリーム モジュールについて詳しく理解し、ストリームの概念と使い方を紹介します。
stream モジュールは、Node の非常にコアなモジュールです。fs、http などの他のモジュールはすべて、stream モジュールのインスタンスに基づいています。 。
ほとんどのフロントエンド初心者にとって、Node を初めて使い始めるときは、ストリームの概念と使用法をまだ明確に理解していません。なぜなら、「ストリーム」についてはほとんど理解されていないからです。フロントエンド作業関連アプリケーションを処理します。
「流れ」という単純な単語から、水の流れ、流れなどの概念が簡単に得られます。
公式定義: ストリームは、Node.js でストリーム データを処理するために使用される抽象インターフェイスです。
公式定義から、次のことがわかります。
ストリームを正確に理解すると、データの流れとして理解できます。
(データ送信手段) アプリケーションでは、ストリームは開始点と終了点を持つ順序付けされたデータ フローです。
ストリームがよく理解できない主な理由は、ストリームが抽象的な概念であるためです。
ストリーム モジュールを明確に理解するために、まず、具体的なアプリケーション シナリオを使用してストリーム モジュールの実際のアプリケーションを説明しましょう。 Node 内の
stream ストリームは、主に 大量のデータ
の処理要件 (大きなファイルの fs の読み取りと書き込み、http リクエストの応答、ファイル圧縮、データの暗号化/復号化など) で使用されます。およびその他のアプリケーション。
上の図を使用してストリームの使用法を説明します。バケットは データ ソース
、プールは # として理解できます。 ##data target 、中間接続パイプライン。
データ フロー 、
データ フロー パイプライン を通じて、データ ソースからデータ ターゲットへのデータ フローとして理解できます。
: データを書き込むことができるストリーム
: はい データを読み取るストリーム
: Readable および
Writable
: データの書き込みおよび読み取り中にデータを変更または変換できるストリーム Duplex すべてのストリームは
。つまり、イベント メカニズムを通じてデータ フローの変化を監視できます。 4. データ モードとキャッシュ領域
4 種類のストリームの具体的な使用方法を学ぶ前に、2 つの概念
これは、次の学習フローでの理解を深めるのに役立ちます。 4.1 データ モード
Node.js API によって作成されたすべてのストリームは、strings および
専用です。操作対象の Buffer (または Uint8Array
) オブジェクト。 4.2 バッファ
Writable ストリームと
Readable ストリームはどちらも、データを内部バッファに保存します。バッファ。 <p>バッファリングできるデータの量は、ストリームのコンストラクターに渡される <code>highWaterMark
オプションによって異なります。通常のストリームの場合、highWaterMark
オプションは バイトの合計数を指定します
;オブジェクト モードで動作するストリームの場合、highWaterMark
オプションはオブジェクトの総数を指定します。
highWaterMark
オプションは、制限ではなくしきい値です。ストリームが追加のデータの要求を停止する前にバッファリングするデータ量を決定します。
実装が stream.push(chunk)
を呼び出すと、データは Readable
ストリームにキャッシュされます。ストリームのコンシューマーが stream.read()
を呼び出さない場合、データは消費されるまで内部キューに残ります。
内部読み取りバッファーの合計サイズが highWaterMark
で指定されたしきい値に達すると、現在バッファリングされているデータが消費されるまで、ストリームは基礎となるリソースからのデータの読み取りを一時的に停止します。
writable.write(chunk) メソッドが繰り返し呼び出される場合、データは Writable
ストリームにキャッシュされます。
##5.1 ストリーム読み取りの流れと一時停止
Readable ストリームは効果的に実行されます。フローモードと一時停止モードの 2 つのモードのいずれかです。
import path from 'path';
import fs, { read } from 'fs';
const filePath = path.join(path.resolve(), 'files', 'text.txt');
const readable = fs.createReadStream(filePath);
// 如果使用 readable.setEncoding() 方法为流指定了默认编码,则监听器回调将把数据块作为字符串传入;否则数据将作为 Buffer 传入。
readable.setEncoding('utf8');
let str = '';
readable.on('open', (fd) => {
console.log('开始读取文件')
})
// 每当流将数据块的所有权移交给消费者时,则会触发 'data' 事件
readable.on('data', (data) => {
str += data;
console.log('读取到数据')
})
// 方法将导致处于流动模式的流停止触发 'data' 事件,切换到暂停模式。 任何可用的数据都将保留在内部缓冲区中。
readable.pause();
// 方法使被显式暂停的 Readable 流恢复触发 'data' 事件,将流切换到流动模式。
readable.resume();
// 当调用 stream.pause() 并且 readableFlowing 不是 false 时,则会触发 'pause' 事件。
readable.on('pause', () => {
console.log('读取暂停')
})
// 当调用 stream.resume() 并且 readableFlowing 不是 true 时,则会触发 'resume' 事件。
readable.on('resume', () => {
console.log('重新流动')
})
// 当流中没有更多数据可供消费时,则会触发 'end' 事件。
readable.on('end', () => {
console.log('文件读取完毕');
})
// 当流及其任何底层资源(例如文件描述符)已关闭时,则会触发 'close' 事件。
readable.on('close', () => {
console.log('关闭文件读取')
})
// 将 destWritable 流绑定到 readable,使其自动切换到流动模式并将其所有数据推送到绑定的 Writable。 数据流将被自动管理
readable.pipe(destWriteable)
// 如果底层流由于底层内部故障而无法生成数据,或者当流实现尝试推送无效数据块时,可能会发生这种情况。
readable.on('error', (err) => {
console.log(err)
console.log('文件读取发生错误')
})
書き込み可能ストリームは読み取り可能ストリームと似ており、データがオーバーフローすると、バッファに直接書き込まれます。エリア。書き込み速度が遅い場合、または書き込みが一時停止されている場合、データ ストリームはキャッシュ領域にキャッシュされます。プレッシャー」、この時点で、プロデューサーに生産を一時停止するように指示する必要があります。キューが解放されると、書き込み可能ストリームは、生産を再開するためにプロデューサーにドレイン メッセージを送信します。
6.2 書き込み可能なストリームの例import path from 'path'; import fs, { read } from 'fs'; const filePath = path.join(path.resolve(), 'files', 'text.txt'); const copyFile = path.join(path.resolve(), 'files', 'copy.txt'); let str = ''; // 创建可读流 const readable = fs.createReadStream(filePath); // 如果使用 readable.setEncoding() 方法为流指定了默认编码 readable.setEncoding('utf8'); // 创建可写流 const wirteable = fs.createWriteStream(copyFile); // 编码 wirteable.setDefaultEncoding('utf8'); readable.on('open', (fd) => { console.log('开始读取文件') }) // 每当流将数据块的所有权移交给消费者时,则会触发 'data' 事件 readable.on('data', (data) => { str += data; console.log('读取到数据'); // 写入 wirteable.write(data, 'utf8'); }) wirteable.on('open', () => { console.log('开始写入数据') }) // 如果对 stream.write(chunk) 的调用返回 false,则 'drain' 事件将在适合继续将数据写入流时触发。 // 即生产数据的速度大于写入速度,缓存区装满之后,会暂停生产着从底层读取数据 // writeable缓存区释放之后,会发送一个drain事件让生产者继续读取 wirteable.on('drain', () => { console.log('继续写入') }) // 在调用 stream.end() 方法之后,并且所有数据都已刷新到底层系统,则触发 'finish' 事件。 wirteable.on('finish', () => { console.log('数据写入完毕') }) readable.on('end', () => { // 数据读取完毕通知可写流 wirteable.end() }) // 当在可读流上调用 stream.pipe() 方法将此可写流添加到其目标集时,则触发 'pipe' 事件。 // readable.pipe(destWriteable) wirteable.on('pipe', () => { console.log('管道流创建') }) wirteable.on('error', () => { console.log('数据写入发生错误') })
以上がNodejs のコア モジュールであるストリーム モジュールについて話しましょう (使い方を参照)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。