Signatur
Beschreibung
ByteLengthQueuingStrategy ist eine fertige Warteschlangenstrategie, die man als zweites Argument an new ReadableStream(), new WritableStream() oder als Strategie für TransformStream übergibt. Sie legt fest, wie viele Daten ein Stream intern puffern darf, bevor er Gegendruck meldet. Gemessen wird dabei nicht in Chunks, sondern in Bytes: Die Größe jedes Chunks ergibt sich aus dessen Eigenschaft byteLength.
Das ist sinnvoll, wenn deine Chunks binäre Daten sind, also ArrayBuffer, Uint8Array oder andere TypedArrays bzw. DataViews. Chunks können unterschiedlich groß sein. Mit einer Byte-Grenze bleibt der Speicherverbrauch trotzdem vorhersagbar, zum Beispiel „höchstens 64 KiB puffern“.
Die Instanz hat zwei nur lesbare Eigenschaften:
highWaterMark: die im Konstruktor angegebene Obergrenze in Bytes.size(chunk): eine Funktion, diechunk.byteLengthzurückgibt.
Der Stream vergleicht die Summe aller gepufferten Größen mit highWaterMark. Wird die Grenze erreicht, sinkt controller.desiredSize bzw. writer.desiredSize auf 0 oder darunter. Außerdem ruft ein ReadableStream dann pull() nicht mehr auf, und writer.ready bleibt ausstehend. Für Streams mit beliebigen JavaScript-Werten ist stattdessen CountQueuingStrategy passend.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $options Pflicht | { highWaterMark: number } | Konfigurationsobjekt. Das Feld highWaterMark ist Pflicht. Fehlt es, wirft der Konstruktor einen TypeError. |
|
| $options.highWaterMark Pflicht | number | Gesamtzahl an Bytes, die der Stream puffern darf, bevor Gegendruck ausgelöst wird. Nicht-negative Zahl; 0 bedeutet: nichts im Voraus puffern. |
Rückgabewert
highWaterMark (number) und size(chunk) (liefert chunk.byteLength).Beispiele
Instanziierung und Eigenschaften
const strategy = new ByteLengthQueuingStrategy({ highWaterMark: 16 * 1024 });
console.log(strategy.highWaterMark);
console.log(strategy.size(new Uint8Array(512)));
console.log(strategy.size(new ArrayBuffer(2048)));
ReadableStream mit Byte-Grenze beim Erzeugen von Zufallsdaten
let produced = 0;
const stream = new ReadableStream({
pull(controller) {
// Nur aufgerufen, solange weniger als 8 KiB gepuffert sind
const chunk = crypto.getRandomValues(new Uint8Array(1024));
controller.enqueue(chunk);
produced += chunk.byteLength;
console.log(`erzeugt: ${produced}, desiredSize: ${controller.desiredSize}`);
if (produced >= 4096) controller.close();
}
}, new ByteLengthQueuingStrategy({ highWaterMark: 8 * 1024 }));
const reader = stream.getReader();
let total = 0;
for (;;) {
const { done, value } = await reader.read();
if (done) break;
total += value.byteLength;
}
console.log('gelesen:', total);
WritableStream mit Gegendruck: auf writer.ready warten
const sink = new WritableStream({
async write(chunk) {
// Langsames Ziel simulieren, z. B. Upload oder Festplatte
await new Promise((r) => setTimeout(r, 50));
console.log('geschrieben:', chunk.byteLength, 'Bytes');
}
}, new ByteLengthQueuingStrategy({ highWaterMark: 4096 }));
const writer = sink.getWriter();
for (let i = 0; i < 4; i++) {
await writer.ready; // blockiert, wenn mehr als 4 KiB gepuffert sind
writer.write(new Uint8Array(3000));
console.log('desiredSize:', writer.desiredSize);
}
await writer.close();
// Wichtig · Fallstricke
- Nur für binäre Chunks: Die Funktion
size()liestchunk.byteLength. Strings haben diese Eigenschaft nicht. Die Größe ist dannundefined, undenqueue()bzw.write()scheitern mit einemRangeError. Strings solltest du vorher mitTextEncoderumwandeln oderCountQueuingStrategyverwenden. - Keine eigenen Byte-Streams: Bei
new ReadableStream({ type: 'bytes' })darf keinesize-Funktion übergeben werden. Übergib dort nur{ highWaterMark }als einfaches Objekt, sonst wird einRangeErrorgeworfen. highWaterMarkist eine Empfehlung, keine harte Grenze.enqueue()undwrite()nehmen auch bei negativerdesiredSizeweitere Chunks an. Gegendruck wirkt nur, wenn Quelle oder SchreiberdesiredSizebzw.writer.readytatsächlich beachten.- Statt einer Instanz kannst du auch ein eigenes Objekt
{ highWaterMark, size(chunk) { … } }übergeben. Die eingebaute Klasse ist aber klarer und wird von der Laufzeitumgebung besser optimiert. - Kompatibilität: Wird in Chrome, Edge, Firefox und Safari unterstützt, außerdem in Web Workers. In Node.js ist die Klasse ab Version 18 global verfügbar, davor über
require('node:stream/web').