Start · Sprachen · JavaScript · Referenz · ReadableByteStreamController.desiredSize

ReadableByteStreamController.desiredSize

Eigenschaft

Gibt an, wie viele Bytes noch in die interne Warteschlange eines Byte-Streams passen, bis dessen <code>highWaterMark</code> erreicht ist. Der Wert kann auch negativ oder <code>null</code> sein.

seit JavaScript Chrome/Edge 89+, Firefox 102+, Node.js 18+ (Safari Kategorie: webapi

Signatur

ReadableByteStreamController.desiredSize

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 highWaterMark erreicht 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

Typ
number | null
Beschreibung
Die Anzahl der Bytes bis zur gewünschten Füllhöhe. Die Zahl kann negativ sein. Bei einem geschlossenen Stream ist der Wert 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);
16 6 -4 null 0

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`);
Gelesen: 1200 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);
Pausiert, desiredSize = 0 Fertig: 640 Bytes