Signatur
Beschreibung
TextEncoderStream ist die Stream-Variante von TextEncoder aus der Encoding API. Es handelt sich um ein Transform-Stream-Paar aus writable (nimmt Zeichenketten entgegen) und readable (liefert Uint8Array-Blöcke mit UTF-8-Bytes). Deshalb lässt es sich direkt in ReadableStream.prototype.pipeThrough() einsetzen.
Man nutzt es immer dann, wenn Text schrittweise erzeugt und als Bytes weitergereicht werden soll, etwa für einen Streaming-Upload per fetch(), zum Schreiben in einen FileSystemWritableFileStream, für die Kompression mit CompressionStream oder in eine serielle Schnittstelle (Web Serial). Der Text muss dabei nicht erst komplett im Speicher liegen.
Wichtig: TextEncoderStream kann Surrogatpaare korrekt verarbeiten, die über zwei Chunks verteilt sind. Ein hohes Surrogat am Ende eines Chunks wird zurückgehalten, bis der nächste Chunk ankommt. Die Ausgabe ist immer UTF-8, ein anderes Encoding lässt sich nicht wählen. Die Eigenschaft encoding liefert deshalb stets "utf-8".
Eigenschaften (alle schreibgeschützt): encoding (immer "utf-8"), readable (ReadableStream<Uint8Array>) und writable (WritableStream<string>).
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $(keine) | — | Der Konstruktor new TextEncoderStream() hat keine Parameter. Das Ziel-Encoding ist fest UTF-8. |
Rückgabewert
readable, writable und encoding. Sie lässt sich als Transform-Stream an pipeThrough() übergeben.Beispiele
Instanziierung und direkte Nutzung von writable/readable
const encoder = new TextEncoderStream();
console.log(encoder.encoding);
const writer = encoder.writable.getWriter();
const reader = encoder.readable.getReader();
// Schreiben und Lesen parallel, sonst blockiert der Backpressure-Mechanismus
writer.write('Grüße');
writer.close();
const { value } = await reader.read();
console.log(value);
Text-Stream per pipeThrough in Bytes umwandeln
const zeilen = ['Zeile 1\n', 'Zeile 2\n', 'Ümlaut 3\n'];
const textStream = new ReadableStream({
start(controller) {
zeilen.forEach((z) => controller.enqueue(z));
controller.close();
}
});
const byteStream = textStream.pipeThrough(new TextEncoderStream());
let gesamt = 0;
for await (const chunk of byteStream) {
gesamt += chunk.byteLength;
}
console.log(`Bytes: ${gesamt}`);
Text komprimiert als Blob erzeugen
const csv = ReadableStream.from(['id;name\n', '1;Anna\n', '2;Jörg\n']);
const gzipStream = csv
.pipeThrough(new TextEncoderStream())
.pipeThrough(new CompressionStream('gzip'));
const blob = await new Response(gzipStream).blob();
console.log(blob.size > 0);
Streaming-Upload mit fetch (Chromium)
const quelle = new ReadableStream({
async start(controller) {
for (let i = 0; i < 3; i++) {
controller.enqueue(`Event ${i}\n`);
await new Promise((r) => setTimeout(r, 500));
}
controller.close();
}
});
await fetch('/api/log', {
method: 'POST',
headers: { 'Content-Type': 'text/plain; charset=utf-8' },
body: quelle.pipeThrough(new TextEncoderStream()),
duplex: 'half' // Pflicht bei Stream-Bodies
});
// Wichtig · Fallstricke
- Nur Zeichenketten schreiben: Andere Werte werden per
String()umgewandelt. Ein Objekt wird so zu"[object Object]". Für JSON also vorherJSON.stringify()aufrufen. - Nur UTF-8: Andere Encodings wie ISO-8859-1 oder UTF-16 werden nicht unterstützt. Für das Dekodieren gibt es das Gegenstück
TextDecoderStream, das mehrere Encodings kann. - Backpressure: Wenn man über
writer.write()schreibt, ohne diereadable-Seite zu lesen, bleibt das zurückgegebene Promise hängen. Deshalb nicht mitawaitaufwrite()warten, bevor ein Leser aktiv ist. - Einzelne Surrogate: Ein hohes Surrogat ohne Partner am Ende des Streams wird als Ersatzzeichen U+FFFD (
EF BF BD) ausgegeben. - Kompatibilität: Seit 2022 in allen aktuellen Browsern verfügbar (Firefox erst ab Version 105). In Node.js gibt es die Schnittstelle ab 16.6 über
stream/webund ab 18 global.ReadableStream.from()und Stream-Bodies beifetch(duplex: 'half') werden nicht überall unterstützt. - Für einmalige, vollständig vorliegende Texte ist
TextEncoder.prototype.encode()einfacher und schneller.