Start · Sprachen · JavaScript · Referenz · DecompressionStream.readable

DecompressionStream.readable

Eigenschaft

Schreibgeschützte Eigenschaft, die den <code>ReadableStream</code> eines <code>DecompressionStream</code> liefert, aus dem die dekomprimierten Daten als <code>Uint8Array</code>-Chunks gelesen werden.

seit JavaScript Baseline 2023: Chrome 80+, Edge 80+, Firefox 113+, Kategorie: webapi

Signatur

DecompressionStream.readable

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

Typ
ReadableStream<Uint8Array>
Beschreibung
Ein 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));
(die ersten 80 Zeichen des entpackten Logs)

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);
true 48 Hallo, Streams! Hallo, Streams! Hallo, Streams!

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');
Entpackte Größe: 104857 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, wird readable mit einem TypeError in den Fehlerzustand versetzt. reader.read() bzw. Response.text() lehnt dann ab – immer mit try...catch absichern.
  • Nachfolgende Daten: Folgen nach dem Ende des komprimierten Datenstroms noch weitere Bytes, führt das ebenfalls zu einem Fehler.
  • Sperre: Nach getReader() oder pipeTo()/pipeThrough() ist der Stream gesperrt (locked === true); ein zweiter Reader wirft einen TypeError. Für mehrere Leser tee() verwenden.
  • Rückstau (Backpressure): Wird readable nicht gelesen, stauen sich Daten und Schreibvorgänge auf writable werden nicht aufgelöst. Beim manuellen Schreiben das Lesen parallel starten und await writer.write() nicht vor dem Lesen blockieren lassen.
  • Automatische Dekompression: Bei fetch() mit Content-Encoding: gzip entpackt der Browser bereits selbst – ein zusätzlicher DecompressionStream wü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.