Start · Sprachen · JavaScript · Referenz · new ReadableStreamDefaultReader()

new ReadableStreamDefaultReader()

Methode

Erstellt einen <code>ReadableStreamDefaultReader</code>, der den übergebenen <code>ReadableStream</code> sperrt und dessen Chunks einzeln lesbar macht.

seit JavaScript Baseline: alle modernen Browser (seit 2022 weitgeh Kategorie: webapi

Signatur

new ReadableStreamDefaultReader(stream)

Beschreibung

Der Konstruktor ReadableStreamDefaultReader() erzeugt ein Leser-Objekt für einen ReadableStream. Sobald der Leser erstellt ist, gilt der Stream als gesperrt (stream.locked === true): Nur dieser Leser kann jetzt Daten entnehmen, bis er mit releaseLock() wieder freigegeben wird.

In der Praxis ruft man den Konstruktor selten direkt auf, sondern verwendet stream.getReader(), das intern genau dasselbe macht. Der direkte Aufruf ist gleichwertig und kann nützlich sein, wenn man den Typ explizit machen möchte oder mit Unterklassen bzw. Polyfills arbeitet.

Über den Leser liest man mit read() Chunk für Chunk; jedes Ergebnis ist ein Objekt { value, done }. Mit cancel() bricht man den Stream ab, über die Promise closed erfährt man, wann der Stream geschlossen oder fehlerhaft beendet wurde.

Typische Einsatzfälle sind das schrittweise Verarbeiten eines fetch()-Antwortkörpers (response.body), Fortschrittsanzeigen beim Download oder das Konsumieren selbst erzeugter Streams.

Parameter

Name Typ Default Beschreibung
$stream Pflicht ReadableStream Der ReadableStream, der gelesen werden soll. Er darf noch nicht gesperrt sein.

Rückgabewert

Typ
ReadableStreamDefaultReader
Beschreibung
Ein neuer Leser, der an den übergebenen Stream gebunden ist und ihn sperrt.

Beispiele

Leser direkt per Konstruktor erzeugen

const stream = new ReadableStream({
  start(controller) {
    controller.enqueue('Hallo');
    controller.enqueue('Welt');
    controller.close();
  }
});

const reader = new ReadableStreamDefaultReader(stream);
console.log(stream.locked);

const readAll = async () => {
  while (true) {
    const { value, done } = await reader.read();
    if (done) break;
    console.log(value);
  }
};

await readAll();
true Hallo Welt

Download-Fortschritt eines fetch()-Körpers anzeigen

const response = await fetch('https://example.com/datei.bin');
const total = Number(response.headers.get('Content-Length')) || 0;
const reader = new ReadableStreamDefaultReader(response.body);

let received = 0;
const chunks = [];

while (true) {
  const { value, done } = await reader.read();
  if (done) break;
  chunks.push(value);
  received += value.byteLength;
  if (total) console.log(`Fortschritt: ${Math.round((received / total) * 100)} %`);
}

const blob = new Blob(chunks);
console.log(`Fertig: ${blob.size} Bytes`);
Fortschritt: 25 % … Fertig: 1048576 Bytes

Fehler bei bereits gesperrtem Stream und Sperre freigeben

const stream = new ReadableStream();
const first = new ReadableStreamDefaultReader(stream);

try {
  new ReadableStreamDefaultReader(stream);
} catch (err) {
  console.log(err.name);
}

first.releaseLock();
const second = new ReadableStreamDefaultReader(stream);
console.log('Zweiter Leser aktiv:', stream.locked);
TypeError Zweiter Leser aktiv: true

// Wichtig · Fallstricke

  • TypeError: Wird geworfen, wenn stream kein ReadableStream ist oder bereits gesperrt ist (stream.locked === true).
  • Solange ein Leser aktiv ist, schlagen pipeTo(), pipeThrough(), tee() und getReader() auf demselben Stream fehl. Nach dem Lesen daher releaseLock() aufrufen, falls der Stream weiterverwendet werden soll.
  • Bei Byte-Streams (type: 'bytes') funktioniert dieser Leser ebenfalls; für Zero-Copy-Lesen in eigene Puffer ist jedoch ReadableStreamBYOBReader gedacht.
  • Für einfaches Durchlaufen ist in neueren Umgebungen for await (const chunk of stream) bequemer – asynchrone Iteration von Streams wird aber noch nicht überall unterstützt (u. a. Safari erst in neueren Versionen).
  • Der direkte Konstruktor-Aufruf wird in allen modernen Browsern unterstützt; stream.getReader() ist die verbreitetere und etwas ältere Variante.