Start · Sprachen · JavaScript · Referenz · CountQueuingStrategy

CountQueuingStrategy

Schnittstelle

Eingebaute Warteschlangen-Strategie der Streams API, die jeden Chunk unabhängig von seiner Größe als 1 zählt und so den Rückstau (Backpressure) über die Anzahl der Chunks steuert.

seit JavaScript Baseline: alle modernen Browser (seit 2022), Node. Kategorie: webapi

Signatur

interface CountQueuingStrategy

Beschreibung

CountQueuingStrategy ist eine von zwei eingebauten Warteschlangen-Strategien der Streams API. Sie wird als zweites Argument an die Konstruktoren von ReadableStream, WritableStream oder (als zweites bzw. drittes Argument) an TransformStream übergeben und legt fest, wie viele Chunks sich in der internen Warteschlange ansammeln dürfen, bevor Rückstau (Backpressure) signalisiert wird.

Die Strategie ist denkbar einfach: Ihre Methode size() liefert für jeden Chunk immer 1. Die highWaterMark gibt also die Anzahl der Chunks an, ab der der Stream als „voll“ gilt. Bei einem ReadableStream wird pull() dann nicht mehr aufgerufen und controller.desiredSize wird ≤ 0; bei einem WritableStream wird writer.ready erst wieder erfüllt, wenn sich die Warteschlange geleert hat.

Einsetzen sollten Sie CountQueuingStrategy, wenn Ihre Chunks Objekte ähnlicher „Kosten“ sind – etwa Datensätze, Log-Einträge oder JSON-Nachrichten. Wenn die Chunks Binärdaten unterschiedlicher Länge sind und der Speicherverbrauch zählt, ist die ByteLengthQueuingStrategy die bessere Wahl.

Die Instanz besitzt die schreibgeschützte Eigenschaft highWaterMark sowie die Methode size(chunk). Das gleiche Verhalten erhält man auch mit einem einfachen Objektliteral { highWaterMark: n }, da Streams ohne size-Funktion jeden Chunk ebenfalls als 1 zählen.

Parameter

Name Typ Default Beschreibung
$options Pflicht { highWaterMark: number } Konfigurationsobjekt für den Konstruktor new CountQueuingStrategy(options).
$options.highWaterMark Pflicht number Maximale Anzahl an Chunks in der internen Warteschlange, bevor Rückstau signalisiert wird. Nicht-negative Zahl; 0 bedeutet: keine Pufferung im Voraus.

Rückgabewert

Typ
CountQueuingStrategy
Beschreibung
Eine neue Strategie-Instanz mit highWaterMark (Zahl) und size() (liefert immer 1).

Beispiele

Instanz erzeugen und Eigenschaften prüfen

const strategy = new CountQueuingStrategy({ highWaterMark: 3 });

console.log(strategy.highWaterMark);
console.log(strategy.size('beliebiger Chunk'));
console.log(strategy.size(new Uint8Array(1024)));
3 1 1

ReadableStream mit begrenztem Vorab-Puffer

let counter = 0;

const stream = new ReadableStream(
  {
    pull(controller) {
      counter++;
      console.log(`pull #${counter}, desiredSize vorher: ${controller.desiredSize}`);
      controller.enqueue({ id: counter });
      if (counter === 5) controller.close();
    },
  },
  new CountQueuingStrategy({ highWaterMark: 2 })
);

// Ohne Leser werden nur 2 Chunks vorab geholt
setTimeout(async () => {
  for await (const chunk of stream) {
    console.log('gelesen:', chunk.id);
  }
}, 100);
pull #1, desiredSize vorher: 2 pull #2, desiredSize vorher: 1 … danach weitere pulls beim Lesen, gelesen: 1 … gelesen: 5

Backpressure beim WritableStream beachten

const sink = new WritableStream(
  {
    async write(record) {
      // Simuliert langsames Speichern, z. B. in eine Datenbank
      await new Promise((r) => setTimeout(r, 50));
      console.log('gespeichert:', record.name);
    },
  },
  new CountQueuingStrategy({ highWaterMark: 2 })
);

const writer = sink.getWriter();
const records = ['Anna', 'Ben', 'Clara', 'David'].map((name) => ({ name }));

for (const record of records) {
  await writer.ready; // wartet, solange 2 Datensätze in der Warteschlange liegen
  console.log('desiredSize:', writer.desiredSize);
  writer.write(record);
}
await writer.close();
desiredSize: 2 desiredSize: 1 … gespeichert: Anna … gespeichert: Ben … gespeichert: Clara gespeichert: David

// Wichtig · Fallstricke

  • Anzahl statt Größe: Jeder Chunk zählt als 1 – ein 100-MB-Puffer genauso wie ein einzelnes Byte. Für Binärdaten mit schwankender Größe besser ByteLengthQueuingStrategy verwenden, sonst kann der Speicherverbrauch trotz kleiner highWaterMark stark wachsen.
  • Keine Bytestreams: Bei new ReadableStream({ type: 'bytes' }) darf keine Strategie mit size-Funktion übergeben werden – das führt zu einem RangeError. Dort nur { highWaterMark: n } angeben.
  • Standardwerte: Ohne Strategie verwenden ReadableStream und WritableStream intern eine Zählstrategie mit highWaterMark: 1; die lesbare Seite eines TransformStream nutzt 0.
  • Pflichtfeld: Fehlt highWaterMark im Konstruktor-Objekt, wird ein TypeError ausgelöst. Negative Werte oder NaN führen beim Erstellen des Streams zu einem RangeError.
  • Kompatibilität: In allen aktuellen Browsern (Chrome, Edge, Firefox, Safari) sowie in Web Workers verfügbar. In Node.js ab Version 18 global, vorher über require('node:stream/web').