ストリーム - 決定版ガイド

Streams API でストリームの読み取り、書き込み、変換を行う方法について説明します。

Streams API を使用すると、ネットワーク経由で受信したデータのストリームにプログラムからアクセスできます。 なんらかの方法でローカルに作成されたり JavaScript で処理します。ストリーミングでは、受信、送信、または変換するリソースの分類が必要です。 分割し、少しずつ処理するということです。ストリーミングは ウェブページに表示する HTML や動画などのアセットを受け取ると、ブラウザは 2015 年にストリームを使用した fetch が導入されるまでは、JavaScript で機能を使用できませんでした。

以前は、なんらかのリソース(動画やテキスト ファイルなど)を処理する場合、 ファイル全体をダウンロードして、適切な形式にシリアル化解除されるのを待つ必要があります。 処理しますストリーミングは これがすべて変更されますJavaScript を使用して元データを段階的に処理し、 クライアントで使用できるようになるとすぐに発行されます。バッファ、文字列、blob を生成する必要はありません。 これによりさまざまなユースケースが可能になります。その一部を以下に示します。

  • ビデオ エフェクト: 読み取り可能な動画ストリームを、エフェクトを適用する変換ストリームにパイプします。 リアルタイムで分析できます
  • データ(解凍): 選択的に変換ストリームにファイル ストリームをパイプで渡す 解凍します。
  • 画像のデコード: バイトをデコードする変換ストリームに HTTP レスポンス ストリームをパイプ処理します。 ビットマップ データに変換してから、ビットマップを PNG に変換する別の変換ストリームで変換します。条件 Service Worker の fetch ハンドラ内にインストールされるため、 新しい画像形式に対応できます

ブラウザ サポート

ReadableStream と WritableStream

対応ブラウザ

  • Chrome: 43。 <ph type="x-smartling-placeholder">
  • Edge: 14。 <ph type="x-smartling-placeholder">
  • Firefox: 65。 <ph type="x-smartling-placeholder">
  • Safari: 10.1。 <ph type="x-smartling-placeholder">

ソース

TransformStream

対応ブラウザ

  • Chrome: 67。 <ph type="x-smartling-placeholder">
  • Edge: 79。 <ph type="x-smartling-placeholder">
  • Firefox: 102。 <ph type="x-smartling-placeholder">
  • Safari: 14.1。 <ph type="x-smartling-placeholder">

ソース

基本コンセプト

さまざまなタイプのストリームについて詳しく説明する前に、基本コンセプトをいくつか紹介します。

チャンク

チャンクとは、ストリームに対して読み書きされる単一のデータです。任意の値を指定できます。 type;ストリームにはさまざまなタイプのチャンクを含めることができますほとんどの場合、チャンクはアトミックな 単位を指定します。たとえば、バイト ストリームは 16 個のチャンクで構成される 1 バイトではなく KiB Uint8Array 単位。

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

読み取り可能ストリームは、読み取り可能なデータのソースを表します。言い換えれば、データは ストリームから取り出します具体的には、読み取り可能なストリームは ReadableStream のインスタンスです。 クラスです。

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

書き込み可能なストリームは、書き込み可能なデータの宛先を表します。言い換えれば、データは 入るということです。具体的には、書き込み可能なストリームは、 WritableStream クラス。

変換ストリーム

変換ストリームは、ストリームのペアで構成されます。ストリームのペアは、書き込み可能側と呼ばれる書き込み可能なストリームです。 読み取り可能ストリーム(読み取り側)があります これを実際にたとえれば、 同時通訳 ある言語を別の言語にリアルタイムに翻訳できます 変換ストリームに固有の方法で、 新しいデータが BigQuery から読み取ることが あります。具体的には、writable プロパティと readable プロパティを持つオブジェクトはすべて配信可能です。 変換ストリームとして受け取りますただし、標準の TransformStream クラスを使用すると、 適切に絡み合ったペアになります

パイプチェーン

ストリームは主に、互いに「パイプ」で処理する場合に使用します。読み取り可能なストリームは、 読み取り可能なストリームの pipeTo() メソッドを使用して書き込み可能なストリームにエクスポートするか、 読み取り可能なストリームの pipeThrough() メソッドを使用します。 パイプでつながれた複数のストリームをパイプ チェーンと呼びます。

バックプレッシャー

パイプ チェーンが構築されると、チャンクの流速に関するシグナルが伝播される できます。チェーン内のステップでまだチャンクを受け入れることができない場合、シグナルを逆方向に伝播する 最終的に元のソースに対してチャンクの生成を停止するよう指示されるまで、 迅速に提供できます。フローを正規化するこのプロセスは、バックプレッシャーと呼ばれます。

ティーイング

読み取り可能なストリームは、tee() メソッドを使用して ted(大文字の「T」の形にちなんで名付けられます)できます。 この操作を行うと、ストリームがロックされ、直接使用できなくなります。ただし、新しい ストリーム(ブランチと呼ばれます)で、個別に使用できます。 ライブ配信の巻き戻しや再開ができないため、ティーイングは重要です。これについては後述します。

<ph type="x-smartling-placeholder">
</ph> フェッチ API の呼び出しからの読み取り可能なストリームで構成されるパイプ チェーンの図。このストリームは変換ストリームを介してパイプされ、出力が T アウトされ、ブラウザに送られる最初の読み取り可能なストリーム、2 番目の読み取り可能なストリームは Service Worker のキャッシュに送信されます。
パイプチェーン。

読み取り可能なストリームの仕組み

読み取り可能ストリームとは、JavaScript で ReadableStream オブジェクトで ソースからデータを取り込みます。「 ReadableStream() コンストラクタは、指定されたハンドラから読み取り可能なストリーム オブジェクトを作成して返します。2 つのモデル 基になるソースのタイプ:

  • push ソースは、アクセスすると常にデータを push します。ソースのソースは ストリームへのアクセスを開始、一時停止、キャンセルできます。たとえば、ライブ動画ストリーム、サーバー送信イベント、 WebSocket です
  • pull ソースは、接続後に明示的にデータをリクエストする必要があります。例 fetch() または XMLHttpRequest 呼び出しによる HTTP オペレーションが含まれます。

ストリーム データは、チャンクと呼ばれる小さな断片で順次読み取られます。 ストリームに配置されたチャンクは「エンキューされる」と呼ばれます。これはキューで待機していることを意味します 読み取る準備が整います内部キューは、まだ読み取られていないチャンクを追跡します。

キューイング戦略は、 その内部キューの状態を確認できます。キューイング戦略では、各チャンクにサイズを割り当て、 キュー内のすべてのチャンクの合計サイズを指定された数まで増やすことをハイ ウォーターマークと呼びます。

ストリーム内のチャンクはリーダーによって読み取られます。このリーダーは、データをチャンクごとに 1 つずつ取得し、 それに対してどんな操作を実行できるでしょうか。リーダーと 一緒に作成される処理コードをコンシューマと呼びます。

次の構文はコントローラと呼ばれます。読み取り可能な各ストリームには その名のとおり、ストリームをコントロールできます。

ストリームを読み取ることができるリーダーは一度に 1 つのみです。リーダーが作成され、ストリームの読み取りを開始したとき (つまり、「アクティブなリーダー」になると「ロック」されます。別の読者に引き継ぐ場合 ストリームを読み取る場合、通常は他の処理を行う前に、最初のリーダーを解放する必要があります。 (ただし、ライブ配信は可能です)。

読み取り可能なストリームの作成

コンストラクタを呼び出して、読み取り可能なストリームを作成します。 ReadableStream()。 このコンストラクタには、オブジェクトを表すオプションの引数 underlyingSource があります。 作成されたストリーム インスタンスの動作を定義するメソッドとプロパティが含まれています。

underlyingSource

これには、次のデベロッパー定義のメソッド(省略可)を使用できます。

  • start(controller): オブジェクトが作成されるとすぐに呼び出されます。「 メソッドはストリーム ソースにアクセスし、 ストリーミング機能の設定に必要です。このプロセスを非同期で行う場合、メソッドは 成功または失敗を通知する Promise を返します。このメソッドに渡される controller パラメータは次のとおりです。 ReadableStreamDefaultController
  • pull(controller): より多くのチャンクがフェッチされるたびに、ストリームを制御するために使用できます。これは、 ストリームの内部のチャンクのキューがいっぱいでなければ、キュー ハイウォーターマークに達しますpull() の呼び出し結果が Promise の場合、 その Promise が履行されるまで、pull() は再度呼び出されることはありません。 Promise が拒否された場合、ストリームはエラーになります。
  • cancel(reason): ストリーム コンシューマがストリームをキャンセルしたときに呼び出されます。
const readableStream = new ReadableStream({
  start(controller) {
    /* … */
  },

  pull(controller) {
    /* … */
  },

  cancel(reason) {
    /* … */
  },
});

ReadableStreamDefaultController は、次のメソッドをサポートしています。

/* … */
start(controller) {
  controller.enqueue('The first chunk!');
},
/* … */

queuingStrategy

同様にオプションの ReadableStream() コンストラクタの 2 番目の引数は queuingStrategy です。 これは、オプションでストリームのキューイング戦略を定義するオブジェクトで、 parameters:

  • highWaterMark: このキュー戦略を使用したストリームのハイ ウォーターマークを示す負でない数値。
  • size(chunk): 指定されたチャンク値の負でない有限サイズを計算して返す関数。 結果はバックプレッシャーを判断するために使用され、適切な ReadableStreamDefaultController.desiredSize プロパティによって示されます。 また、基になるソースの pull() メソッドが呼び出されるタイミングも管理されます。
で確認できます。
const readableStream = new ReadableStream({
    /* … */
  },
  {
    highWaterMark: 10,
    size(chunk) {
      return chunk.length;
    },
  },
);