Signatur
Beschreibung
Die schreibgeschützte Eigenschaft desiredSize eines ReadableByteStreamController gibt an, wie viele Bytes der Stream noch aufnehmen möchte, bevor seine interne Warteschlange die gewünschte Füllhöhe (highWaterMark) erreicht. Sie wird als highWaterMark − aktuell gepufferte Bytes berechnet.
Über diesen Wert steuert eine Datenquelle den Gegendruck (Backpressure). Liest der Konsument langsamer, als die Quelle Daten liefert, füllt sich die Warteschlange und desiredSize sinkt auf 0 oder darunter. Das ist das Zeichen für die Quelle, mit dem Einreihen neuer Daten per enqueue() zu pausieren. Bei Pull-Quellen erledigt der Stream das meist von selbst, weil er pull() nur aufruft, wenn Bedarf besteht. Bei Push-Quellen wie WebSockets, Sensoren oder Timern musst du desiredSize selbst prüfen.
Mögliche Werte:
- positive Zahl: So viele Bytes haben noch Platz, bis
highWaterMarkerreicht ist. 0: Die Warteschlange ist genau voll. Diesen Wert liefert die Eigenschaft auch, wenn der Stream geschlossen ist.- negative Zahl: Die Warteschlange ist übervoll, weil mehr eingereiht wurde als gewünscht.
null: Der Stream ist in einem Fehlerzustand (errored).
Rückgabewert
0, bei einem Stream im Fehlerzustand null.Beispiele
Werte von desiredSize in den verschiedenen Zuständen
let ctrl;
const stream = new ReadableStream(
{ type: 'bytes', start(controller) { ctrl = controller; } },
{ highWaterMark: 16 } // 16 Bytes gewünschte Füllhöhe
);
console.log(ctrl.desiredSize); // leer
ctrl.enqueue(new Uint8Array(10));
console.log(ctrl.desiredSize); // 16 - 10
ctrl.enqueue(new Uint8Array(10));
console.log(ctrl.desiredSize); // übervoll
ctrl.error(new Error('Quelle defekt'));
console.log(ctrl.desiredSize); // Fehlerzustand
// Geschlossener Stream mit leerer Warteschlange
let ctrl2;
new ReadableStream({ type: 'bytes', start(c) { ctrl2 = c; } }, { highWaterMark: 16 });
ctrl2.close();
console.log(ctrl2.desiredSize);
Pull-Quelle: Chunk-Größe an desiredSize ausrichten
const data = new TextEncoder().encode('Hallo Welt! '.repeat(100)); // 1200 Bytes
let offset = 0;
const stream = new ReadableStream({
type: 'bytes',
pull(controller) {
// desiredSize kann 0 sein, wenn ein Reader wartet – daher Mindestgröße
const size = Math.max(controller.desiredSize ?? 0, 64);
const chunk = data.slice(offset, offset + size);
offset += chunk.byteLength;
controller.enqueue(chunk);
if (offset >= data.byteLength) controller.close();
}
}, { highWaterMark: 256 });
const reader = stream.getReader();
let total = 0;
while (true) {
const { done, value } = await reader.read();
if (done) break;
total += value.byteLength;
}
console.log(`Gelesen: ${total} Bytes`);
Push-Quelle mit Gegendruck pausieren und fortsetzen
let timer = null;
let counter = 0;
const startProducing = (controller) => {
if (timer) return;
timer = setInterval(() => {
if (controller.desiredSize === null) return clearInterval(timer);
if (controller.desiredSize <= 0) {
// Warteschlange voll → Quelle pausieren
clearInterval(timer);
timer = null;
console.log('Pausiert, desiredSize =', controller.desiredSize);
return;
}
controller.enqueue(new Uint8Array(32).fill(counter++ % 256));
if (counter === 20) { clearInterval(timer); controller.close(); }
}, 5);
};
const stream = new ReadableStream({
type: 'bytes',
start: startProducing,
pull: startProducing // wird aufgerufen, sobald wieder Platz ist
}, { highWaterMark: 128 });
// Langsamer Konsument
const reader = stream.getReader();
setTimeout(async () => {
let bytes = 0;
for (let r = await reader.read(); !r.done; r = await reader.read()) {
bytes += r.value.byteLength;
}
console.log('Fertig:', bytes, 'Bytes');
}, 100);