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 値を設定することが重要です。値が小さすぎるとパフォーマンスが低下し、大きすぎるとメモリ使用量が増加します。