Start · Sprachen · JavaScript · Referenz · WritableStreamDefaultWriter

WritableStreamDefaultWriter

Schnittstelle

Writer-Objekt der Streams-API, das von <code>WritableStream.getWriter()</code> zurückgegeben wird, den Stream exklusiv sperrt und Daten kontrolliert hineinschreibt.

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

Signatur

interface WritableStreamDefaultWriter

Beschreibung

Die Schnittstelle WritableStreamDefaultWriter ist der „Schreibkopf“ eines WritableStream. Einen Writer bekommen Sie über stream.getWriter() oder mit new WritableStreamDefaultWriter(stream). Sobald er existiert, ist der Stream gesperrt (stream.locked === true). Nur dieser Writer darf dann Daten hineinschreiben. So können sich mehrere Produzenten nicht gegenseitig stören.

Die wichtigsten Mitglieder:

  • write(chunk): Stellt einen Chunk in die Warteschlange. Gibt ein Promise zurück, das erfüllt wird, sobald die zugrunde liegende Senke (Sink) den Chunk verarbeitet hat.
  • ready: Ein Promise, das erfüllt wird, sobald desiredSize wieder positiv ist. Damit setzen Sie Backpressure (Gegendruck) korrekt um.
  • desiredSize: Zeigt an, wie viel Platz noch in der internen Warteschlange ist. Der Wert ist null bei einem Fehler und 0 nach dem Schließen.
  • close(): Schließt den Stream geordnet, nachdem alle wartenden Chunks geschrieben wurden.
  • abort(reason): Bricht den Stream sofort ab und verwirft wartende Chunks.
  • closed: Ein Promise, das beim Schließen erfüllt und bei einem Fehler oder nach releaseLock() abgelehnt wird.
  • releaseLock(): Gibt die Sperre frei, damit ein anderer Writer übernehmen kann.

Sie brauchen die Schnittstelle immer dann, wenn Sie Daten Stück für Stück erzeugen und in eine Senke schreiben, etwa in einen Datei-Handle der File System Access API, einen CompressionStream, eine WebTransport- oder WebSocketStream-Verbindung oder die beschreibbare Seite eines TransformStream. Für einfache Weiterleitungen zwischen Streams ist readable.pipeTo(writable) meist bequemer. Diese Methode kümmert sich selbst um Sperren und Backpressure.

Rückgabewert

Typ
WritableStreamDefaultWriter
Beschreibung
Der Konstruktor bzw. getWriter() liefert eine Writer-Instanz. write(), close() und abort() geben jeweils Promise<undefined> zurück. ready und closed sind ebenfalls Promises.

Beispiele

Writer holen und Text in einen Sink schreiben

const chunks = [];
const stream = new WritableStream({
  write(chunk) {
    chunks.push(chunk);
  },
  close() {
    console.log('Fertig:', chunks.join(' '));
  }
});

const writer = stream.getWriter();
console.log(stream.locked);

await writer.write('Hallo');
await writer.write('Streams');
await writer.close();
true Fertig: Hallo Streams

Backpressure mit ready und desiredSize beachten

const stream = new WritableStream(
  {
    async write(chunk) {
      // langsame Senke simulieren
      await new Promise(r => setTimeout(r, 50));
      console.log('geschrieben:', chunk);
    }
  },
  new CountQueuingStrategy({ highWaterMark: 2 })
);

const writer = new WritableStreamDefaultWriter(stream);

for (let i = 1; i <= 4; i++) {
  await writer.ready; // warten, bis wieder Platz ist
  console.log('desiredSize vor write:', writer.desiredSize);
  writer.write(`Zeile ${i}`).catch(console.error);
}
await writer.close();
desiredSize vor write: 2 desiredSize vor write: 1 geschrieben: Zeile 1 ...

Datenstrom komprimieren (CompressionStream)

const cs = new CompressionStream('gzip');
const writer = cs.writable.getWriter();
const encoder = new TextEncoder();

// Schreiben und Lesen parallel, sonst blockiert der Gegendruck
const resultPromise = new Response(cs.readable).arrayBuffer();

for (const zeile of ['a,b,c', '1,2,3', '4,5,6']) {
  await writer.ready;
  await writer.write(encoder.encode(zeile + '\n'));
}
await writer.close();

const gz = await resultPromise;
console.log('gzip-Bytes:', gz.byteLength);
gzip-Bytes: 41 (ungefähr)

Fehlerfall: abbrechen und Sperre freigeben

const stream = new WritableStream({
  abort(reason) {
    console.log('Senke abgebrochen:', reason);
  }
});
const writer = stream.getWriter();

writer.closed.catch(err => console.log('closed abgelehnt:', err));

await writer.abort('Benutzer hat abgebrochen');
writer.releaseLock();
console.log('locked:', stream.locked);
Senke abgebrochen: Benutzer hat abgebrochen closed abgelehnt: Benutzer hat abgebrochen locked: false

// Wichtig · Fallstricke

  • Sperre: Solange ein Writer aktiv ist, wirft ein zweites getWriter() einen TypeError. Auch pipeTo() auf diesen Stream schlägt dann fehl. Rufen Sie releaseLock() auf, wenn Sie den Stream weitergeben wollen.
  • Backpressure: write() ohne vorheriges await writer.ready füllt die Warteschlange unbegrenzt und kann viel Speicher verbrauchen. Achten Sie besonders bei TransformStream darauf, die lesbare Seite parallel zu verbrauchen. Sonst wird ready nie erfüllt, und Ihr Code hängt fest (Deadlock).
  • Nicht behandelte Ablehnungen: Wenn Sie Promises von write() nicht mit await abwarten, sollten Sie .catch() anhängen. Andernfalls erzeugen Fehler der Senke Warnungen der Form unhandledrejection.
  • releaseLock() lehnt die Promises closed und ready dieses Writers ab. Der Stream selbst bleibt dabei offen.
  • close() und abort() unterscheiden sich: close() schreibt zuerst alle wartenden Chunks. abort() verwirft sie.
  • Kompatibilität: Die Schnittstelle wird von Chrome 59+ und Edge unterstützt, von Firefox erst ab Version 100 und von Safari ab 14.1. In Node.js ist sie seit Version 18 global verfügbar, davor über require('node:stream/web').