Start · Sprachen · JavaScript · Referenz · TransformStream.readable

TransformStream.readable

Eigenschaft

Gibt die schreibgeschützte <code>ReadableStream</code>-Seite eines <code>TransformStream</code> zurück, aus der die transformierten Daten gelesen werden.

seit JavaScript Baseline: alle modernen Browser (seit 2022), Node. Kategorie: webapi

Signatur

get TransformStream.prototype.readable

Beschreibung

Ein TransformStream hat zwei Enden: die writable-Seite, in die du Rohdaten schreibst, und die readable-Seite, aus der die Ergebnisse der transform()-Funktion herauskommen. Die Eigenschaft readable liefert dieses Ausgabe-Ende als ReadableStream.

Praktisch nutzt du readable meist indirekt über ReadableStream.prototype.pipeThrough(): Diese Methode erwartet ein Objekt der Form { writable, readable }, leitet den Quell-Stream in writable und gibt readable zurück. Direkt greifst du auf readable zu, wenn du den Stream z. B. als Response-Body weiterreichst, mit getReader() manuell ausliest, per for await...of iterierst oder an einen Worker überträgst.

Die Eigenschaft ist schreibgeschützt und liefert bei jedem Zugriff dasselbe Objekt. Der zurückgegebene Stream unterliegt den üblichen Regeln: Er kann nur von einem Leser gleichzeitig gesperrt werden (locked), und der Rückstau (Backpressure) wird automatisch an die writable-Seite weitergegeben.

Rückgabewert

Typ
ReadableStream
Beschreibung
Das lesbare Ende des Transformations-Streams. Es liefert die Chunks, die der Transformer per controller.enqueue() ausgibt.

Beispiele

Text in Großbuchstaben umwandeln und manuell auslesen

const upper = new TransformStream({
  transform(chunk, controller) {
    controller.enqueue(chunk.toUpperCase());
  }
});

const writer = upper.writable.getWriter();
const reader = upper.readable.getReader();

// Schreiben und Lesen parallel, sonst blockiert der Rückstau
const schreiben = (async () => {
  await writer.write('hallo ');
  await writer.write('welt');
  await writer.close();
})();

let ergebnis = '';
while (true) {
  const { value, done } = await reader.read();
  if (done) break;
  ergebnis += value;
}
await schreiben;
console.log(ergebnis);
HALLO WELT

Verwendung mit pipeThrough() und fetch

const response = await fetch('/daten.txt');

// pipeThrough() gibt intern transformStream.readable zurück
const textStream = response.body.pipeThrough(new TextDecoderStream());

for await (const chunk of textStream) {
  console.log('Empfangen:', chunk.length, 'Zeichen');
}
Empfangen: 1024 Zeichen …

readable als Response-Body weiterreichen (Service Worker)

self.addEventListener('fetch', (event) => {
  const { readable, writable } = new TransformStream();

  // Antwort sofort mit der readable-Seite starten
  event.respondWith(new Response(readable, {
    headers: { 'Content-Type': 'text/plain; charset=utf-8' }
  }));

  // Inhalte nachträglich in die writable-Seite streamen
  event.waitUntil((async () => {
    const writer = writable.getWriter();
    const enc = new TextEncoder();
    for (const teil of ['Teil 1\n', 'Teil 2\n']) {
      await writer.write(enc.encode(teil));
    }
    await writer.close();
  })());
});

// Wichtig · Fallstricke

  • Rückstau: Wird aus readable nicht gelesen, füllt sich die interne Warteschlange und await writer.write() kann für immer hängen bleiben. Schreiben und Lesen immer nebenläufig organisieren.
  • Sperre: Nach getReader(), pipeTo() oder pipeThrough() ist readable.locked === true; ein zweiter Leser wirft einen TypeError. Für mehrere Konsumenten readable.tee() verwenden.
  • Abbruch: readable.cancel() bricht auch die writable-Seite mit einem Fehler ab – laufende Schreibvorgänge schlagen dann fehl.
  • Kompatibilität: In allen aktuellen Browsern verfügbar; asynchrone Iteration (for await...of) über ReadableStream wird in Safari erst seit neueren Versionen unterstützt. Übertragung per postMessage (transferable streams) ist nicht überall verfügbar. In Node.js global ab Version 18, davor über require('node:stream/web').