JavaScript/ByteLengthQueuingStrategy
ByteLengthQueuingStrategy オブジェクト
概要
ByteLengthQueuingStrategy
は JavaScript のストリーム API で使用される重要なクラスで、ストリームのバックプレッシャーを制御するために設計されています。このオブジェクトは、チャンクのバイトサイズに基づいてキューイング戦略を実装します。
基本的な使い方
ByteLengthQueuingStrategy
オブジェクトは、チャンクのバイト長を計算し、ストリームのキューが特定のサイズ制限を超えないようにします。
const writableStream = new WritableStream({ write(chunk) { // チャンクの処理 return new Promise(resolve => setTimeout(resolve, 10)); } }, new ByteLengthQueuingStrategy({ highWaterMark: 1024 * 1024 }));
この例では、1MB(1024 * 1024バイト)の highWaterMark
を持つストリームを作成しています。ストリームのバッファが1MBを超えると、書き込み操作は一時停止します。
コンストラクタ
ByteLengthQueuingStrategy
のコンストラクタは、次のようなオプションオブジェクトを受け取ります:
new ByteLengthQueuingStrategy({ highWaterMark });
highWaterMark
パラメータは必須で、キューに許容される最大バイト数を指定します。
メソッド
ByteLengthQueuingStrategy
オブジェクトには以下のメソッドがあります:
// チャンクのサイズを計算するメソッド const size = byteStrategy.size(chunk);
size()
メソッドは、与えられたチャンクのバイト長を返します。デフォルトでは、チャンクの byteLength
プロパティか length
プロパティを使用します。
実際の使用例
ReadableStream
と WritableStream
の両方で ByteLengthQueuingStrategy
を使用する例を見てみましょう:
// 大きなデータを生成する関数 function generateData(size) { return new Uint8Array(size).fill(65); // すべて 'A' で埋める } // ReadableStream の作成 const readableStream = new ReadableStream({ start(controller) { // 開始時に1回だけ実行 this.count = 0; }, pull(controller) { // データが必要な時に呼び出される if (this.count < 10) { const chunk = generateData(100000); // 100KB のチャンク controller.enqueue(chunk); this.count++; } else { controller.close(); } } }, new ByteLengthQueuingStrategy({ highWaterMark: 200000 })); // 200KB // WritableStream の作成 const writableStream = new WritableStream({ write(chunk) { console.log(`${chunk.length} バイトのデータを受信`); // 書き込み処理のシミュレーション return new Promise(resolve => setTimeout(resolve, 100)); } }, new ByteLengthQueuingStrategy({ highWaterMark: 300000 })); // 300KB // ストリームのパイピング readableStream.pipeTo(writableStream) .then(() => console.log('転送完了')) .catch(err => console.error('エラーが発生しました:', err));
この例では、ReadableStream
は 200KB の highWaterMark
を持ち、WritableStream
は 300KB の highWaterMark
を持っています。ReadableStream
は 100KB のチャンクを生成し、バックプレッシャーが適用されるまで(バッファが 200KB を超えるまで)チャンクを生成し続けます。
CountQueuingStrategy との比較
JavaScriptのストリームAPIには、ByteLengthQueuingStrategy
に加えて CountQueuingStrategy
もあります。これらの違いを以下の表で比較します:
特性 | ByteLengthQueuingStrategy |
CountQueuingStrategy |
---|---|---|
サイズ計算 | チャンクのバイト長を使用 | すべてのチャンクを1として計算 |
用途 | バイナリデータやサイズが可変のデータ | 均一なサイズのオブジェクト |
精度 | メモリ使用量をより正確に制御 | チャンク数のみを制御 |
デフォルトの size() | byteLength または length を返す | 常に 1 を返す |
カスタムキューイング戦略
ByteLengthQueuingStrategy
が要件に合わない場合は、独自のキューイング戦略を実装することも可能です:
const myStrategy = { highWaterMark: 1024, size(chunk) { // JSON文字列のバイト長を計算する例 return new TextEncoder().encode(JSON.stringify(chunk)).length; } }; const writableStream = new WritableStream({ write(chunk) { console.log('チャンク処理中'); return Promise.resolve(); } }, myStrategy);
この例では、JSON
オブジェクトのバイト長を計算するカスタム戦略を実装しています。
注意事項
ByteLengthQueuingStrategy
を使用する際の重要な考慮事項:
- バイナリデータ(
TypedArray
やArrayBuffer
など)を扱う場合に特に有用です。 - テキストデータの場合、
byteLength
が常に正確なバイト数を表すとは限りません。UTF-8 エンコーディングではマルチバイト文字が存在します。 - ブラウザによって実装が異なる場合があるため、クロスブラウザ互換性をテストすることが重要です。
効率的なストリーム処理のためには、データの性質に応じて適切な highWaterMark
値を設定することが重要です。値が小さすぎるとパフォーマンスが低下し、大きすぎるとメモリ使用量が増加します。