検索
ホームページウェブフロントエンドjsチュートリアルNode.js でのストリーム読み取り可能なストリームの使用

読み取り可能なストリームとは、プログラムで使用するためのデータ を生成するストリームです。一般的なデータ生成方法には、ディスク ファイルの読み取り、ネットワーク リクエスト コンテンツの読み取りなどが含まれます。ストリームとは何かについての前の例を見てください。

const rs = fs.createReadStream(filePath);
rs は読み取り可能なストリームであり、そのデータ生成方法は次のとおりです。 read ディスク ファイル、コンソール process.stdin も読み取り可能なストリームです:

process.stdin.pipe(process.stdout);
簡単な文でコンソール入力を出力できます。 process.stdin がデータを生成する方法は、コンソールでのユーザーの入力を読み取ることです。の入力です。

読み取り可能なストリームの定義を振り返ってください。

読み取り可能なストリームは、プログラムで使用するデータを生成するストリームです。

カスタム読み取り可能なストリーム


提供されるシステムに加えて

fs.CreateReadStream

使用される gulp またはヴァイナル-fs によって提供される src メソッドも読み取り可能なストリームを使用します

gulp.src(['*.js', 'dist/**/*.scss'])
特定の方法でデータを生成し、それをプログラムに渡して消費したい場合、どのように始めればよいでしょうか?

これは 2 つの簡単な手順で実行できます。

    ストリーム モジュールの
  1. Readable

    クラスを継承します。
  2. Rewrite
  3. _read

    メソッド、
    this.push

    を呼び出して、生成されたデータをキューに入れて読み取ります
  4. #Readable クラスは、readable ストリームで行うべき作業のほとんどが完了しているので、それを継承し、_read メソッドにデータを生成するメソッドを記述するだけで、カスタム readable ストリームを実装できます。

例: 100 ミリ秒ごとに乱数を生成するストリームを実装します (役に立ちません)

const Readable = require('stream').Readable;
class RandomNumberStream extends Readable {
    constructor(max) {
        super()
    }
    _read() {
        const ctx = this;
        setTimeout(() => {
            const randomNumber = parseInt(Math.random() * 10000);
            // 只能 push 字符串或 Buffer,为了方便显示打一个回车
            ctx.push(`${randomNumber}\n`);
        }, 100);
    }
}
module.exports = RandomNumberStream;

コードのクラス継承部分は非常に単純です。主に、 _read メソッドには、いくつかの注意すべき点があります。

Readable クラスにはデフォルトで _read メソッドが実装されていますが、何も行われません。 #_read メソッドにはパラメータ size があり、どれだけのデータを読み取って read メソッドに返すかを指定するために使用されますが、これは単なる参照データです。多くの実装ではこのパラメータが無視され、ここでも無視されます。詳細は後述
  1. これを介してバッファにプッシュする データをプッシュする、バッファの概念は後述しますが、とりあえず水道管に押し込んで消費できることが分かります
  2. プッシュのコンテンツは文字列またはバッファのみであり、数値は使用できません。
  3. プッシュ メソッドには次のパラメータがあります。最初のパラメータが文字列の場合、2 番目のパラメータ エンコーディングはエンコーディングを指定するために使用されます。
  4. 実行して効果を確認してください
  5. const RandomNumberStream = require('./RandomNumberStream');
    const rns = new RandomNumberStream();
    rns.pipe(process.stdout);
  6. このように、コントロールに数値が連続的に表示されていることがわかりますプラットフォーム上では、乱数を生成する読み取り可能なストリームが実装されています。解決すべき小さな問題がいくつかあります

停止方法

100 ミリ秒ごとに数値をバッファにプッシュすると、たとえば、ローカル ファイルを読み取る場合、常に終了します。データが読み取られたことを示しますか?

null をバッファにプッシュするだけです。消費者が必要な乱数の数を定義できるようにコードを変更します:

const Readable = require('stream').Readable;
class RandomNumberStream extends Readable {
    constructor(max) {
        super()
        this.max = max;
    }
    _read() {
        const ctx = this;
        setTimeout(() => {
            if (ctx.max) {
                const randomNumber = parseInt(Math.random() * 10000);
                // 只能 push 字符串或 Buffer,为了方便显示打一个回车
                ctx.push(`${randomNumber}\n`);
                ctx.max -= 1;
            } else {
                ctx.push(null);
            }
        }, 100);
    }
}
module.exports = RandomNumberStream;

コードは最大識別子を使用して、消費者がニーズを指定できるようにします。インスタンス化時に文字数を指定できます

const RandomNumberStream = require('./');
const rns = new RandomNumberStream(5);
rns.pipe(process.stdout);

このようにすると、コンソールに 5 文字しか出力されないことがわかります

なぜ setInterval ではなく setTimeout なのでしょうか

注意してください学生は、100 ミリ秒ごとの乱数の生成では setInterval を呼び出すのではなく、setTimeout を使用することに気づいたかもしれませんが、結果が正しいのに、遅延するだけで繰り返されないのはなぜでしょうか。

#これには、ストリームが機能する 2 つの方法を理解する必要があります

#フロー モード: データは基礎となるシステムによって読み取られ、できるだけ早くアプリケーションに提供されます

一時停止モード: 複数のデータ ブロックを読み取るには、read() メソッドを明示的に呼び出す必要があります

    ストリームはデフォルトで一時停止モードになっており、プログラムは明示的に read() メソッドを呼び出す必要があります。ただし、上記の例では、pipe() メソッドによってストリームがフロー モードに切り替わるため、呼び出すことなくデータを取得できます。そのため、データが読み込まれるまで _read() メソッドが自動的に繰り返し呼び出されるので、そのたびに_read() メソッドでデータを読み取る必要があるのは 1 回だけです。
  1. フロー モードと一時停止モードの切り替え
  2. 次のメソッドを使用して、ストリームをデフォルトの一時停止モードからフローに切り替えることができます。 mode:

データ イベント リスナーを追加してデータ監視を開始する

resume() メソッドを呼び出してデータ フローを開始する

pipe() メソッドを呼び出して、データを別の書き込み可能なストリームに転送します
  1. フロー モードから一時停止モードに切り替える方法は 2 つあります。
  2. ストリームに Pipe() がない場合、 stop() メソッドはストリームを一時停止できます
pipe() すべてのデータ イベント リスナーを削除し、unpipe() メソッドを呼び出します

#data event
  1. 使用後Pipe() メソッドを使用すると、データは読み取り可能なストリームからストリーミングされます 書き込み可能なストリームに入りましたが、ユーザーにとってはブラック ボックスに見えます データはどのように流れるのでしょうか?フロー モードと一時停止モードを切り替えるときに重要な用語が 2 つあります。
  2. #フロー モードに対応するデータ イベント
一時停止モードに対応する read() メソッド

これら 2 つのメカニズムは、プログラムがデータ フローを駆動できる理由です。最初にフロー モードのデータ イベントを見てみましょう。読み取り可能なストリームのデータ イベントが監視されると、ストリームはフロー モードに入ります。上記のストリームを呼び出すコードを書き換えることができます。

const RandomNumberStream = require('./RandomNumberStream');
const rns = new RandomNumberStream(5);
rns.on('data', chunk => {
  console.log(chunk);
});

这样可以看到控制台打印出了类似下面的结果

<buffer>
<buffer>
<buffer>
<buffer>
<buffer></buffer></buffer></buffer></buffer></buffer>

当可读流生产出可供消费的数据后就会触发 data 事件,data 事件监听器绑定后,数据会被尽可能地传递。data 事件的监听器可以在第一个参数收到可读流传递过来的 Buffer 数据,这也就是控制台打印的 chunk,如果想显示为数字,可以调用 Buffer 的 toString() 方法

当数据处理完成后还会触发一个

end

事件,因为流的处理不是同步调用,所以如果希望完事后做一些事情就需要监听这个事件,在代码最后追加一句:

rns.on('end', () => {
  console.log('done');
});复制代码

这样可以在数据接收完了显示 done ,当然数据处理过程中出现了错误会触发 error 事件,可以监听做异常处理:

rns.on('error', (err) => {
  console.log(err);
});复制代码

read(size)

流在暂停模式下需要程序显式调用 read() 方法才能得到数据,read() 方法会从内部缓冲区中拉取并返回若干数据,当没有更多可用数据时,会返回null

使用 read() 方法读取数据时,如果传入了 size 参数,那么它会返回指定字节的数据;当指定的size字节不可用时,则返回null。如果没有指定size参数,那么会返回内部缓冲区中的所有数据

现在有一个矛盾,在流动模式下流生产出了数据,然后触发 data 事件通知给程序,这样很方便。在暂停模式下需要程序去读取,那么就有一种可能是读取的时候还没生产好,如果使用轮询的方式未免效率有些低

NodeJS 提供了一个

readable的事件,事件在可读流准备好数据的时候触发,也就是先监听这个事件,收到通知有数据了再去读取就好了:

const rns = new RandomNumberStream(5);
rns.on('readable', () => {
  let chunk;
  while((chunk = rns.read()) !== null){
    console.log(chunk);
  }
});

这样可以读取到数据,值得注意的一点是并不是每次调用 read() 方法都可以返回数据,前面提到了如果可用的数据没有达到 size 那么返回 null,所以在程序中加了个判断

数据会不会漏掉

const stream = fs.createReadStream('/dev/input/event0');
stream.on('readable', callback);复制代码

在流动模式会不会有这样的问题:可读流在创建好的时候就生产数据了,如果在绑定 readable 事件之前就生产了某些数据,触发了 readable 事件,在极端情况下会造成数据丢失吗?

事实并不会,按照 NodeJS event loop 程序创建流和调用事件监听在一个事件队列里面,生产数据和事件监听都是异步操作,而 on 监听事件使用了 process.nextTick 会保证在数据生产之前被绑定好,相关知识可以看定时器章节中对 event loop 的解读

到这里可能对 data事件、readable事件触发时机, read() 方法每次读多少数据,什么时候返回 null 还有一定的疑问,在后续可写流章节会在 back pressure 部分结合源码介绍相关机制

推荐教程:《JS教程

以上がNode.js でのストリーム読み取り可能なストリームの使用の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明
この記事は掘金社区で複製されています。侵害がある場合は、admin@php.cn までご連絡ください。
JavaScriptエンジン:実装の比較JavaScriptエンジン:実装の比較Apr 13, 2025 am 12:05 AM

さまざまなJavaScriptエンジンは、各エンジンの実装原則と最適化戦略が異なるため、JavaScriptコードを解析および実行するときに異なる効果をもたらします。 1。語彙分析:ソースコードを語彙ユニットに変換します。 2。文法分析:抽象的な構文ツリーを生成します。 3。最適化とコンパイル:JITコンパイラを介してマシンコードを生成します。 4。実行:マシンコードを実行します。 V8エンジンはインスタントコンピレーションと非表示クラスを通じて最適化され、Spidermonkeyはタイプ推論システムを使用して、同じコードで異なるパフォーマンスパフォーマンスをもたらします。

ブラウザを超えて:現実世界のJavaScriptブラウザを超えて:現実世界のJavaScriptApr 12, 2025 am 12:06 AM

現実世界におけるJavaScriptのアプリケーションには、サーバー側のプログラミング、モバイルアプリケーション開発、モノのインターネット制御が含まれます。 2。モバイルアプリケーションの開発は、ReactNativeを通じて実行され、クロスプラットフォームの展開をサポートします。 3.ハードウェアの相互作用に適したJohnny-Fiveライブラリを介したIoTデバイス制御に使用されます。

next.jsを使用してマルチテナントSaaSアプリケーションを構築する(バックエンド統合)next.jsを使用してマルチテナントSaaSアプリケーションを構築する(バックエンド統合)Apr 11, 2025 am 08:23 AM

私はあなたの日常的な技術ツールを使用して機能的なマルチテナントSaaSアプリケーション(EDTECHアプリ)を作成しましたが、あなたは同じことをすることができます。 まず、マルチテナントSaaSアプリケーションとは何ですか? マルチテナントSaaSアプリケーションを使用すると、Singの複数の顧客にサービスを提供できます

next.jsを使用してマルチテナントSaaSアプリケーションを構築する方法(フロントエンド統合)next.jsを使用してマルチテナントSaaSアプリケーションを構築する方法(フロントエンド統合)Apr 11, 2025 am 08:22 AM

この記事では、許可によって保護されたバックエンドとのフロントエンド統合を示し、next.jsを使用して機能的なedtech SaaSアプリケーションを構築します。 FrontEndはユーザーのアクセス許可を取得してUIの可視性を制御し、APIリクエストがロールベースに付着することを保証します

JavaScript:Web言語の汎用性の調査JavaScript:Web言語の汎用性の調査Apr 11, 2025 am 12:01 AM

JavaScriptは、現代のWeb開発のコア言語であり、その多様性と柔軟性に広く使用されています。 1)フロントエンド開発:DOM操作と最新のフレームワーク(React、Vue.JS、Angularなど)を通じて、動的なWebページとシングルページアプリケーションを構築します。 2)サーバー側の開発:node.jsは、非ブロッキングI/Oモデルを使用して、高い並行性とリアルタイムアプリケーションを処理します。 3)モバイルおよびデスクトップアプリケーション開発:クロスプラットフォーム開発は、反応および電子を通じて実現され、開発効率を向上させます。

JavaScriptの進化:現在の傾向と将来の見通しJavaScriptの進化:現在の傾向と将来の見通しApr 10, 2025 am 09:33 AM

JavaScriptの最新トレンドには、TypeScriptの台頭、最新のフレームワークとライブラリの人気、WebAssemblyの適用が含まれます。将来の見通しは、より強力なタイプシステム、サーバー側のJavaScriptの開発、人工知能と機械学習の拡大、およびIoTおよびEDGEコンピューティングの可能性をカバーしています。

javascriptの分解:それが何をするのか、なぜそれが重要なのかjavascriptの分解:それが何をするのか、なぜそれが重要なのかApr 09, 2025 am 12:07 AM

JavaScriptは現代のWeb開発の基礎であり、その主な機能には、イベント駆動型のプログラミング、動的コンテンツ生成、非同期プログラミングが含まれます。 1)イベント駆動型プログラミングにより、Webページはユーザー操作に応じて動的に変更できます。 2)動的コンテンツ生成により、条件に応じてページコンテンツを調整できます。 3)非同期プログラミングにより、ユーザーインターフェイスがブロックされないようにします。 JavaScriptは、Webインタラクション、シングルページアプリケーション、サーバー側の開発で広く使用されており、ユーザーエクスペリエンスとクロスプラットフォーム開発の柔軟性を大幅に改善しています。

pythonまたはjavascriptの方がいいですか?pythonまたはjavascriptの方がいいですか?Apr 06, 2025 am 12:14 AM

Pythonはデータサイエンスや機械学習により適していますが、JavaScriptはフロントエンドとフルスタックの開発により適しています。 1. Pythonは、簡潔な構文とリッチライブラリエコシステムで知られており、データ分析とWeb開発に適しています。 2。JavaScriptは、フロントエンド開発の中核です。 node.jsはサーバー側のプログラミングをサポートしており、フルスタック開発に適しています。

See all articles

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser は、オンライン試験を安全に受験するための安全なブラウザ環境です。このソフトウェアは、あらゆるコンピュータを安全なワークステーションに変えます。あらゆるユーティリティへのアクセスを制御し、学生が無許可のリソースを使用するのを防ぎます。

EditPlus 中国語クラック版

EditPlus 中国語クラック版

サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

WebStorm Mac版

WebStorm Mac版

便利なJavaScript開発ツール