Start · Sprachen · JavaScript · Referenz · TextEncoderStream.readable

TextEncoderStream.readable

Eigenschaft

Schreibgeschützte Eigenschaft, die den <code>ReadableStream</code> eines <code>TextEncoderStream</code> liefert, aus dem UTF-8-kodierte Bytes als <code>Uint8Array</code>-Blöcke gelesen werden.

seit JavaScript Baseline 2023: alle modernen Browser (Chrome 71, F Kategorie: webapi

Signatur

get TextEncoderStream.prototype.readable

Beschreibung

Ein TextEncoderStream ist ein Transform-Stream: Auf der beschreibbaren Seite (writable) gibt man Zeichenketten hinein, auf der lesbaren Seite (readable) kommen die zugehörigen UTF-8-Bytes als Uint8Array-Blöcke heraus. Die Eigenschaft readable gibt dir genau diese Ausgabeseite als ReadableStream<Uint8Array>.

Meistens greift man nicht direkt auf readable zu. Stattdessen reicht man den ganzen TextEncoderStream an ReadableStream.prototype.pipeThrough() weiter, und das Ergebnis von pipeThrough() ist dann genau dieser readable-Stream. Direkt brauchst du die Eigenschaft, wenn du selbst schreibst (über writable.getWriter()) und die Bytes separat weiterverarbeiten willst, zum Beispiel als Request-Body für fetch(), für einen CompressionStream oder für eine Datei-Schreiboperation.

Die Kodierung ist immer UTF-8, andere Zeichensätze gibt es nicht. Anders als ein einfaches TextEncoder.encode() in einer Schleife kommt der Stream mit Surrogatpaaren zurecht, die auf zwei Blöcke verteilt sind: Ein einzelnes hohes Surrogat am Ende eines Blocks wird zurückgehalten, bis der nächste Block ankommt.

Rückgabewert

Typ
ReadableStream<Uint8Array>
Beschreibung
Die lesbare Seite des Transform-Streams. Jeder gelesene Block ist ein Uint8Array mit UTF-8-Bytes. Bei jedem Zugriff kommt dasselbe Objekt zurück.

Beispiele

Zeichenketten schreiben und Bytes direkt lesen

const encoder = new TextEncoderStream();
const writer = encoder.writable.getWriter();
const reader = encoder.readable.getReader();

// Schreiben und Lesen laufen parallel, sonst droht Rückstau (Backpressure)
const writing = (async () => {
  await writer.write('Hallo ');
  await writer.write('Wält');
  await writer.close();
})();

const chunks = [];
while (true) {
  const { value, done } = await reader.read();
  if (done) break;
  chunks.push(value);
}
await writing;

console.log(chunks.map((c) => Array.from(c)));
[ [72, 97, 108, 108, 111, 32], [87, 195, 164, 108, 116] ]

Typischer Einsatz mit pipeThrough()

const textStream = new ReadableStream({
  start(controller) {
    controller.enqueue('Zeile 1\n');
    controller.enqueue('Zeile 2 – mit Umlaut ü\n');
    controller.close();
  }
});

// pipeThrough() gibt encoder.readable zurück
const byteStream = textStream.pipeThrough(new TextEncoderStream());

const buffer = await new Response(byteStream).arrayBuffer();
console.log(buffer.byteLength);
36

Text kodieren, komprimieren und hochladen

const encoder = new TextEncoderStream();

// readable weiter in einen CompressionStream leiten
const gzipped = encoder.readable.pipeThrough(new CompressionStream('gzip'));

const writer = encoder.writable.getWriter();
writer.write(JSON.stringify({ log: 'Ereignis', ts: Date.now() }));
writer.close();

// Streaming-Upload (Chromium: duplex: 'half' ist Pflicht)
const response = await fetch('/api/logs', {
  method: 'POST',
  headers: { 'Content-Encoding': 'gzip' },
  body: gzipped,
  duplex: 'half'
});
console.log(response.status);
200

// Wichtig · Fallstricke

  • Schreibgeschützt: Wenn du readable etwas zuweist, passiert nichts. Im Strict Mode gibt es einen TypeError, weil nur ein Getter existiert.
  • Sperre: Sobald getReader() aufgerufen oder der Stream mit pipeTo()/pipeThrough() verbunden ist, ist er gesperrt (readable.locked === true). Ein zweiter Leser führt zu einem TypeError. Mehrere Konsumenten bekommst du nur über tee().
  • Rückstau (Backpressure): Wenn du auf writer.write() wartest, ohne dass jemand parallel aus readable liest, kann das Programm hängen bleiben. Lies deshalb gleichzeitig oder verbinde die Streams über pipeThrough().
  • Die Blockgrenzen der Ausgabe folgen den Schreibaufrufen. Leere Zeichenketten erzeugen keinen Block. Nicht-String-Werte werden vorher in Strings umgewandelt.
  • Kompatibilität: Firefox unterstützt die Eigenschaft erst ab Version 105. Streaming-Request-Bodies mit fetch() gehen derzeit nur in Chromium-Browsern und brauchen duplex: 'half'.