Signatur
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
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();
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`);
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);
// Wichtig · Fallstricke
- TypeError: Wird geworfen, wenn
streamkeinReadableStreamist oder bereits gesperrt ist (stream.locked === true). - Solange ein Leser aktiv ist, schlagen
pipeTo(),pipeThrough(),tee()undgetReader()auf demselben Stream fehl. Nach dem Lesen daherreleaseLock()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 jedochReadableStreamBYOBReadergedacht. - 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.