Signatur
Beschreibung
Ein TransformStream hat zwei Seiten: die schreibbare Seite writable und die lesbare Seite readable. Alles, was in writable geschrieben wird, läuft durch die transform()-Funktion des Transformers. Das Ergebnis kann anschließend aus readable gelesen werden.
Direkt verwendet man writable vor allem, wenn man Daten manuell über einen WritableStreamDefaultWriter hineinschreibt (writable.getWriter()) oder einen vorhandenen ReadableStream per readableStream.pipeTo(transform.writable) anschließt. In den meisten Fällen reicht aber readable.pipeThrough(transform), das intern writable und readable verbindet.
Die Eigenschaft ist ein reiner Getter. Sie liefert bei jedem Zugriff dieselbe WritableStream-Instanz, die beim Erzeugen des TransformStream angelegt wurde. Weil { readable, writable } genau die Form ist, die pipeThrough() erwartet, kann man eigene „Transform-Paare“ auch ohne TransformStream bauen.
Rückgabewert
TransformStream. Daten, die hier geschrieben werden, laufen durch den Transformer und landen auf der Seite readable.Beispiele
Manuell in die schreibbare Seite schreiben
const upper = new TransformStream({
transform(chunk, controller) {
controller.enqueue(chunk.toUpperCase());
}
});
const writer = upper.writable.getWriter();
const reader = upper.readable.getReader();
// Schreiben und Lesen nebenläufig, sonst blockiert der Gegendruck (Backpressure)
const schreiben = (async () => {
await writer.write('hallo');
await writer.write('welt');
await writer.close();
})();
const teile = [];
while (true) {
const { value, done } = await reader.read();
if (done) break;
teile.push(value);
}
await schreiben;
console.log(teile);
ReadableStream per pipeTo() anschließen
const quelle = new ReadableStream({
start(controller) {
[1, 2, 3].forEach((n) => controller.enqueue(n));
controller.close();
}
});
const verdoppeln = new TransformStream({
transform(n, controller) {
controller.enqueue(n * 2);
}
});
// Promise nicht awaiten, sonst Deadlock – lesen läuft parallel
quelle.pipeTo(verdoppeln.writable);
for await (const wert of verdoppeln.readable) {
console.log(wert);
}
Text über TextEncoderStream in eine Fetch-Antwort kodieren
const encoder = new TextEncoderStream();
const writer = encoder.writable.getWriter();
writer.write('Zeile 1\n');
writer.write('Zeile 2\n');
writer.close();
// Die lesbare Seite liefert Uint8Array-Chunks
const text = await new Response(encoder.readable).text();
console.log(text);
// Wichtig · Fallstricke
- Deadlock-Gefahr: Wer auf
writer.write()oderpipeTo(transform.writable)wartet, ohne gleichzeitigreadablezu lesen, hängt fest, sobald die Warteschlange voll ist (Backpressure). Schreiben und Lesen deshalb nebenläufig ausführen. - Sperre: Nach
writable.getWriter()ist der Stream gesperrt (writable.locked === true). Ein weiteresgetWriter()oderpipeTo()wirft einenTypeError, biswriter.releaseLock()aufgerufen wurde. - Schreibgeschützt: Eine Zuweisung an
writablebleibt ohne Wirkung und wirft im Strict Mode einenTypeError. - Bricht man
writablemitabort()ab, wird auchreadablein den Fehlerzustand versetzt – und umgekehrt beireadable.cancel(). - Kompatibilität: in Chrome/Edge 67+, Firefox 102+, Safari 14.1+ und Node.js 18+ (global; vorher über
stream/web) verfügbar.