Start · Sprachen · JavaScript · Referenz · WritableStreamDefaultController

WritableStreamDefaultController

Schnittstelle

Controller eines <code>WritableStream</code>, mit dem die zugrunde liegende Senke den Stream in den Fehlerzustand versetzen und auf Abbrüche über ein <code>AbortSignal</code> reagieren kann.

seit JavaScript Baseline: alle modernen Browser (signal: Chrome 98 Kategorie: webapi

Signatur

interface WritableStreamDefaultController

Beschreibung

Ein WritableStreamDefaultController wird nie selbst erzeugt. Der WritableStream-Konstruktor legt ihn automatisch an und übergibt ihn an die Methoden der zugrunde liegenden Senke (underlying sink): an start(controller) und an write(chunk, controller). Über den Controller steuert die Senke den Zustand des Streams von innen heraus.

Die Schnittstelle ist bewusst schlank:

  • controller.error(reason): versetzt den Stream in den Fehlerzustand. Danach schlagen alle weiteren Zugriffe über den Writer fehl, und writer.closed wird mit reason zurückgewiesen.
  • controller.signal: ein AbortSignal, das ausgelöst wird, sobald jemand writer.abort() bzw. stream.abort() aufruft. So lassen sich laufende asynchrone Schreibvorgänge, etwa fetch-Aufrufe, sofort abbrechen, statt zu warten, bis sie fertig sind.

Typische Einsatzfälle sind die Prüfung von Chunks mit gezieltem Fehlschlag, das Abbrechen von Netzwerk-Schreibvorgängen und das Weiterreichen externer Fehler, etwa einer geschlossenen WebSocket-Verbindung. Wenn man den Controller in start() in einer Variablen speichert, kann man error() auch außerhalb der Senken-Methoden aufrufen.

Parameter

Name Typ Default Beschreibung
$reason any undefined Parameter von controller.error(reason): der Fehlergrund, meist ein Error-Objekt. Er wird an wartende Promises des Writers weitergereicht.

Rückgabewert

Typ
WritableStreamDefaultController
Beschreibung
Wird nicht vom Entwickler erzeugt, sondern von der Streams-Implementierung an start() und write() der Senke übergeben. error() gibt undefined zurück, signal liefert ein AbortSignal.

Beispiele

Ungültige Chunks mit controller.error() ablehnen

const log = [];

const stream = new WritableStream({
  write(chunk, controller) {
    if (typeof chunk !== 'string') {
      // Stream dauerhaft in den Fehlerzustand versetzen
      controller.error(new TypeError('Nur Strings erlaubt'));
      return;
    }
    log.push(chunk);
  }
});

const writer = stream.getWriter();
await writer.write('Hallo');
writer.write(42).catch(() => {});

try {
  await writer.closed;
} catch (err) {
  console.log('Stream fehlerhaft:', err.message);
}
console.log(log);
Stream fehlerhaft: Nur Strings erlaubt [ 'Hallo' ]

Laufenden fetch über controller.signal abbrechen

const stream = new WritableStream({
  async write(chunk, controller) {
    controller.signal.addEventListener('abort', () => {
      console.log('Abgebrochen:', controller.signal.reason);
    }, { once: true });

    // Der Upload wird sofort beendet, wenn der Stream abgebrochen wird
    await fetch('/api/log', {
      method: 'POST',
      body: chunk,
      signal: controller.signal
    });
  }
});

const writer = stream.getWriter();
writer.write('Eintrag 1').catch(() => {});
setTimeout(() => writer.abort('Benutzer hat abgebrochen'), 50);
Abgebrochen: Benutzer hat abgebrochen

Controller speichern und externe Fehler weiterreichen

let ctrl;
const socket = new WebSocket('wss://example.com/feed');

const stream = new WritableStream({
  start(controller) {
    ctrl = controller;
    // Erst schreiben, wenn die Verbindung steht
    return new Promise((resolve, reject) => {
      socket.addEventListener('open', resolve, { once: true });
      socket.addEventListener('error', reject, { once: true });
    });
  },
  write(chunk) {
    socket.send(chunk);
  },
  close() {
    socket.close();
  }
});

// Verbindungsabbruch von außen -> Stream geht in den Fehlerzustand
socket.addEventListener('close', () => {
  ctrl.error(new Error('WebSocket-Verbindung geschlossen'));
});

Direkte Instanziierung ist nicht erlaubt

try {
  new WritableStreamDefaultController();
} catch (err) {
  console.log(err instanceof TypeError);
}
true