Signatur
Beschreibung
Der Konstruktor TextEncoderStream() erstellt einen Transform-Stream mit einer writable-Seite (nimmt Strings entgegen) und einer readable-Seite (liefert Uint8Array-Blöcke). Er ist das Stream-Gegenstück zu TextEncoder und hält sich an das TransformStream-Muster. Deshalb lässt er sich direkt mit ReadableStream.prototype.pipeThrough() verwenden.
Einsetzen solltest du ihn immer dann, wenn Text schrittweise entsteht und als Bytes weitergereicht werden muss. Typische Fälle sind Uploads per fetch() mit Streaming-Body, das Schreiben in eine Datei über die File System Access API, die Web Serial API oder das Weiterleiten erzeugter Inhalte in einen CompressionStream. So muss der Gesamttext nie vollständig im Speicher liegen.
Die Kodierung ist immer UTF-8 und lässt sich nicht einstellen. Ersatzzeichenpaare (Surrogate Pairs), die über zwei Chunks verteilt sind, werden korrekt zusammengesetzt. Bleibt am Ende ein einzelnes High-Surrogate übrig, wird es beim Schließen als U+FFFD (EF BF BD) ausgegeben.
Rückgabewert
TextEncoderStream-Objekt mit den Eigenschaften readable (ReadableStream<Uint8Array>), writable (WritableStream<string>) und encoding (immer "utf-8").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 Gegendruck (Backpressure)
writer.write('Grüße');
writer.close();
const { value } = await reader.read();
console.log(value);
String-Stream per pipeThrough in Bytes umwandeln
const lines = ['id;name\n', '1;Müller\n', '2;Öztürk\n'];
const textStream = new ReadableStream({
start(controller) {
lines.forEach((line) => controller.enqueue(line));
controller.close();
}
});
const byteStream = textStream.pipeThrough(new TextEncoderStream());
let total = 0;
for await (const chunk of byteStream) {
total += chunk.byteLength;
}
console.log(`${total} Bytes kodiert`);
Generierten Text komprimiert herunterladen
const makeLog = () => new ReadableStream({
start(controller) {
for (let i = 0; i < 1000; i++) {
controller.enqueue(`Eintrag ${i}: ${new Date().toISOString()}\n`);
}
controller.close();
}
});
const gzipped = makeLog()
.pipeThrough(new TextEncoderStream())
.pipeThrough(new CompressionStream('gzip'));
const blob = await new Response(gzipped).blob();
const url = URL.createObjectURL(blob);
const a = Object.assign(document.createElement('a'), { href: url, download: 'log.txt.gz' });
a.click();
URL.revokeObjectURL(url);
Streaming-Upload mit fetch (Chromium)
const body = new ReadableStream({
async start(controller) {
for (const part of ['Hallo ', 'Server', '!']) {
controller.enqueue(part);
await new Promise((r) => setTimeout(r, 200));
}
controller.close();
}
}).pipeThrough(new TextEncoderStream());
const res = await fetch('/upload', {
method: 'POST',
headers: { 'Content-Type': 'text/plain; charset=utf-8' },
body,
duplex: 'half' // Pflicht bei Stream-Bodys
});
console.log(res.status);
// Wichtig · Fallstricke
- Keine Argumente: Der Konstruktor nimmt keine Kodierung entgegen, es wird immer UTF-8 verwendet. Für andere Zeichensätze gibt es keine native Stream-API.
- Nur Strings schreiben: Nicht-String-Werte werden per
String()umgewandelt. So wird aus einem Objekt z. B."[object Object]". Serialisiere Daten vorher selbst, etwa mitJSON.stringify(). - Leere Chunks: Ein leerer String erzeugt keinen Ausgabe-Chunk.
- Backpressure: Wenn du über
writer.write()schreibst, musst du gleichzeitig diereadable-Seite lesen. Sonst wird das vonwrite()zurückgegebene Promise nicht erfüllt, sobald die Queue voll ist. Warte deshalb nicht mitawaitauf einwrite(), bevor jemand liest. - Ohne
new: Ein Aufruf als normale Funktion wirft einenTypeError. - Kompatibilität: Firefox unterstützt die API erst ab Version 105. In Node.js ist sie ab 16.6 über
stream/webverfügbar und ab 18 global. Sie funktioniert auch in Web Workern. Streaming-Uploads perfetch()mitduplex: 'half'gibt es derzeit nur in Chromium-Browsern.