Start · Sprachen · JavaScript · Referenz · TextEncoderStream.writable

TextEncoderStream.writable

Eigenschaft

Schreibgeschützte Eigenschaft, die die <code>WritableStream</code>-Seite eines <code>TextEncoderStream</code> liefert. Sie nimmt Zeichenketten entgegen, die als UTF-8 codiert werden.

seit JavaScript Baseline 2022: Chrome 71, Firefox 105, Safari 14.1 Kategorie: webapi

Signatur

TextEncoderStream.writable

Beschreibung

Ein TextEncoderStream ist ein Transform-Stream mit zwei Seiten. In die writable-Seite schreibt man Zeichenketten, an der readable-Seite kommen die passenden UTF-8-Bytes als Uint8Array-Blöcke heraus. Die Eigenschaft writable gibt einen WritableStream<string> zurück. Bei jedem Zugriff ist das dasselbe Objekt.

Meist greift man nicht direkt auf writable zu. Stattdessen übergibt man das ganze Objekt an ReadableStream.prototype.pipeThrough(), das intern in writable schreibt und readable weiterreicht. Direkt braucht man writable, wenn man Text selbst in den Stream schreiben will, etwa über writable.getWriter(). Ein Beispiel ist ein Streaming-Upload per fetch(), bei dem die Daten nach und nach erzeugt werden.

Die Codierung ist immer UTF-8. Anders als beim TextDecoderStream kann man keine andere Codierung wählen. Ungepaarte Ersatzzeichen (Surrogates) werden durch U+FFFD ersetzt. Ein hohes Surrogate am Ende eines Blocks wird bis zum nächsten Block zurückgehalten. So bleiben Emojis heil, auch wenn sie auf zwei Schreibaufrufe verteilt sind.

Rückgabewert

Typ
WritableStream<string>
Beschreibung
Die Schreibseite des Transform-Streams. Geschriebene Werte werden in Zeichenketten umgewandelt und als UTF-8-Bytes an readable weitergereicht.

Beispiele

Text direkt schreiben und Bytes lesen

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

// Schreiben und Schließen, ohne auf den Leser zu blockieren
writer.write('Grüße ');
writer.write('👋');
writer.close();

const chunks = [];
while (true) {
  const { value, done } = await reader.read();
  if (done) break;
  chunks.push(...value);
}
console.log(chunks.length, chunks.slice(0, 3));
12 [ 71, 114, 195 ]

Streaming-Upload mit fetch()

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

// Upload startet sofort, Daten folgen nach und nach
const upload = fetch('/api/log', {
  method: 'POST',
  headers: { 'Content-Type': 'text/plain; charset=utf-8' },
  body: encoder.readable,
  duplex: 'half' // Pflicht bei Stream-Bodies
});

for (let i = 1; i <= 3; i++) {
  await writer.write(`Zeile ${i}\n`);
  await new Promise(r => setTimeout(r, 500));
}
await writer.close();

const res = await upload;
console.log(res.status);
200

Über pipeThrough (writable wird intern genutzt)

const textStream = new ReadableStream({
  start(controller) {
    controller.enqueue('Hallo, ');
    controller.enqueue('Welt!');
    controller.close();
  }
});

const byteStream = textStream.pipeThrough(new TextEncoderStream());
const bytes = await new Response(byteStream).arrayBuffer();
console.log(bytes.byteLength);
12

// Wichtig · Fallstricke

  • Nur lesbar: Eine Zuweisung an writable wird ignoriert, im Strict Mode gibt es einen TypeError.
  • Sperre: Nach getWriter() ist der Stream gesperrt (writable.locked === true). pipeThrough() oder pipeTo() schlagen dann fehl, bis der Writer mit releaseLock() freigegeben wird.
  • Gegendruck (Backpressure): Wenn niemand von readable liest, lösen sich die Promises von writer.write() ab dem Füllstand der Warteschlange nicht mehr auf. Wer jeden Aufruf mit await abwartet, ohne dass parallel gelesen wird, blockiert.
  • Werte, die keine Zeichenketten sind, werden mit String() umgewandelt. Aus 123 wird also "123", und Objekte werden zu "[object Object]".
  • Streaming-Request-Bodies mit fetch() brauchen duplex: 'half' und HTTP/2. Firefox und Safari unterstützen sie noch nicht.
  • In Node.js ist TextEncoderStream ab Version 18 global verfügbar, davor über require('node:stream/web').