Signatur
Beschreibung
Die Eigenschaft writable ist die Eingabeseite eines DecompressionStream. Du schreibst komprimierte Chunks vom Typ ArrayBuffer, TypedArray (z. B. Uint8Array) oder DataView hinein, und auf der Ausgabeseite readable kommen die dekomprimierten Bytes als Uint8Array-Chunks wieder heraus.
Da DecompressionStream das Interface GenericTransformStream implementiert, bildet es zusammen mit readable ein { writable, readable }-Paar. Deshalb kannst du die Instanz direkt an ReadableStream.prototype.pipeThrough() übergeben – der häufigste und empfohlene Weg. Den writable-Stream direkt zu nutzen, ist dann sinnvoll, wenn du Daten manuell und schrittweise einspeist, z. B. aus WebSocket-Nachrichten, aus einer eigenen Parsing-Logik oder aus mehreren Quellen.
Beim manuellen Schreiben holst du dir mit getWriter() einen WritableStreamDefaultWriter, schreibst die Chunks mit write() und beendest den Eingabestrom mit close(). Erst nach close() wird der Rest des Formats verarbeitet und readable geschlossen. Parallel dazu musst du readable lesen, sonst füllt sich die interne Warteschlange und der Gegendruck (Backpressure) blockiert weitere Schreibvorgänge.
Rückgabewert
WritableStream, der ArrayBuffer-, TypedArray- oder DataView-Chunks mit komprimierten Daten annimmt. Es wird bei jedem Zugriff dieselbe Instanz zurückgegeben.Beispiele
Manuelles Schreiben in writable und Lesen aus readable
// gzip-komprimierten Text erzeugen und wieder entpacken
const compress = async (text) => {
const stream = new Blob([text]).stream().pipeThrough(new CompressionStream('gzip'));
return new Uint8Array(await new Response(stream).arrayBuffer());
};
const gzipped = await compress('Hallo programmierung.net!');
const ds = new DecompressionStream('gzip');
const writer = ds.writable.getWriter();
// Schreiben und Lesen parallel starten (Backpressure vermeiden)
const textPromise = new Response(ds.readable).text();
await writer.write(gzipped);
await writer.close();
console.log(await textPromise);
Komprimierte Daten in mehreren Chunks einspeisen
const gzipped = new Uint8Array(await new Response(
new Blob(['x'.repeat(10000)]).stream().pipeThrough(new CompressionStream('gzip'))
).arrayBuffer());
const ds = new DecompressionStream('gzip');
const writer = ds.writable.getWriter();
const resultPromise = new Response(ds.readable).arrayBuffer();
// Daten in 16-Byte-Stücken schreiben, z. B. wie sie aus dem Netz kommen
for (let i = 0; i < gzipped.length; i += 16) {
await writer.ready;
writer.write(gzipped.subarray(i, i + 16));
}
await writer.close();
const result = await resultPromise;
console.log(result.byteLength);
Empfohlener Weg: pipeThrough nutzt writable implizit
// Eine .gz-Datei laden und als Text entpacken
const response = await fetch('/daten/log.txt.gz');
const text = await new Response(
response.body.pipeThrough(new DecompressionStream('gzip'))
).text();
console.log(text.slice(0, 100));
Fehler bei ungültigen Daten abfangen
const ds = new DecompressionStream('gzip');
const writer = ds.writable.getWriter();
const reading = new Response(ds.readable).text();
try {
await writer.write(new TextEncoder().encode('kein gzip'));
await writer.close();
await reading;
} catch (err) {
console.log(err.name);
}
// Wichtig · Fallstricke
- Schreibgeschützt: Die Eigenschaft kann nicht neu zugewiesen werden; sie liefert immer denselben
WritableStream. - Nur Binärdaten: Strings werden nicht akzeptiert und führen zu einem
TypeError. Text vorher mitTextEncoderumwandeln – wobei komprimierte Daten ohnehin binär sind. - Deadlock-Gefahr: Wer
await writer.write()aufruft, ohne gleichzeitigreadablezu lesen, kann bei größeren Datenmengen hängen bleiben, weil der Gegendruck die Schreib-Promises nicht auflöst. Lesen immer vorher bzw. parallel starten. - Sperre: Nach
getWriter()ist der Stream gesperrt (locked === true). Danach schlägtpipeThrough()bzw.pipeTo()fehl, biswriter.releaseLock()aufgerufen wird. - Beschädigte oder abgeschnittene Daten führen zu einem
TypeError, der den Stream in den Fehlerzustand versetzt; das zeigt sich meist erst beimclose()oder beim Lesen. - Kompatibilität: Firefox erst ab Version 113, Safari ab 16.4. Das Format
'deflate-raw'wird in älteren Chromium-Versionen (vor 103) nicht unterstützt. In Node.js global ab Version 18 verfügbar. - Sicherheit: Bei Daten aus unsicheren Quellen droht eine Dekompressionsbombe (wenige KB entpacken sich zu GB). Die ausgegebene Datenmenge beim Lesen begrenzen und den Vorgang bei Überschreitung abbrechen.