Signatur
Beschreibung
Die Eigenschaft readable ist die Ausgabeseite eines DecompressionStream. Komprimierte Bytes (gzip, deflate oder deflate-raw), die in die Eingabeseite writable geschrieben werden, kommen hier als dekomprimierte Uint8Array-Chunks wieder heraus. Zusammen bilden writable und readable ein Transform-Stream-Paar und entsprechen damit dem Interface TransformStream.
In der Praxis greift man selten direkt auf readable zu, weil ReadableStream.prototype.pipeThrough() das Objekt { writable, readable } selbst entgegennimmt und den readable-Stream zurückgibt. Direkt nutzt man die Eigenschaft, wenn Schreib- und Leseseite getrennt behandelt werden sollen – etwa wenn Daten stückweise über einen Writer eingespeist und parallel über einen Reader ausgelesen werden.
Der zurückgegebene Stream kann mit getReader(), for await...of, pipeTo() oder über new Response(stream) verarbeitet werden. Letzteres ist besonders praktisch, um das Ergebnis bequem mit .text(), .json() oder .arrayBuffer() einzusammeln.
Rückgabewert
ReadableStream, der die dekomprimierten Daten als Uint8Array-Chunks ausgibt. Es wird bei jedem Zugriff dasselbe Stream-Objekt geliefert.Beispiele
Gzip-Datei per fetch laden und als Text dekomprimieren
const loadGzipText = async (url) => {
const response = await fetch(url);
const ds = new DecompressionStream('gzip');
// pipeThrough() liefert intern ds.readable zurück
const decompressed = response.body.pipeThrough(ds);
return new Response(decompressed).text();
};
const text = await loadGzipText('/daten/log.txt.gz');
console.log(text.slice(0, 80));
Schreib- und Leseseite getrennt verwenden
// Zuerst etwas komprimieren, um Testdaten zu haben
const input = new TextEncoder().encode('Hallo, Streams! '.repeat(3));
const compressed = await new Response(
new Blob([input]).stream().pipeThrough(new CompressionStream('gzip'))
).arrayBuffer();
const ds = new DecompressionStream('gzip');
const writer = ds.writable.getWriter();
writer.write(new Uint8Array(compressed));
writer.close();
// Ausgabe direkt über ds.readable lesen
const reader = ds.readable.getReader();
const decoder = new TextDecoder();
let result = '';
while (true) {
const { value, done } = await reader.read();
if (done) break;
console.log(value instanceof Uint8Array, value.byteLength);
result += decoder.decode(value, { stream: true });
}
result += decoder.decode();
console.log(result);
Dekomprimierte Chunks mit for await...of verarbeiten
const countBytes = async (blob) => {
const ds = new DecompressionStream('deflate');
blob.stream().pipeTo(ds.writable).catch((err) => console.error('Eingabe:', err));
let total = 0;
for await (const chunk of ds.readable) {
total += chunk.byteLength;
}
return total;
};
// Beispiel: Datei aus <input type="file"> auswerten
const file = document.querySelector('#upload').files[0];
console.log('Entpackte Größe:', await countBytes(file), 'Bytes');
// Wichtig · Fallstricke
- Fehlerhafte Eingabedaten: Sind die Daten beschädigt, passen nicht zum gewählten Format (z. B.
'gzip'statt'deflate') oder enden sie vorzeitig, wirdreadablemit einemTypeErrorin den Fehlerzustand versetzt.reader.read()bzw.Response.text()lehnt dann ab – immer mittry...catchabsichern. - Nachfolgende Daten: Folgen nach dem Ende des komprimierten Datenstroms noch weitere Bytes, führt das ebenfalls zu einem Fehler.
- Sperre: Nach
getReader()oderpipeTo()/pipeThrough()ist der Stream gesperrt (locked === true); ein zweiter Reader wirft einenTypeError. Für mehrere Lesertee()verwenden. - Rückstau (Backpressure): Wird
readablenicht gelesen, stauen sich Daten und Schreibvorgänge aufwritablewerden nicht aufgelöst. Beim manuellen Schreiben das Lesen parallel starten undawait writer.write()nicht vor dem Lesen blockieren lassen. - Automatische Dekompression: Bei
fetch()mitContent-Encoding: gzipentpackt der Browser bereits selbst – ein zusätzlicherDecompressionStreamwürde dann fehlschlagen. - Kompatibilität: In allen modernen Browsern verfügbar (Firefox erst ab 113, Safari ab 16.4); in Node.js global ab Version 18.
'deflate-raw'wird in älteren Chromium-Versionen (vor 103) nicht unterstützt. Auch in Web Workern nutzbar.