Start · Sprachen · JavaScript · Referenz · WritableStreamDefaultController.error()

WritableStreamDefaultController.error()

Methode

Versetzt den zugehörigen <code>WritableStream</code> in einen Fehlerzustand. Alle weiteren Schreibzugriffe schlagen dann mit dem übergebenen Grund fehl.

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

Signatur

WritableStreamDefaultController.prototype.error(e)

Beschreibung

Mit error() meldet die zugrunde liegende Senke (das Objekt mit start, write, close und abort, das an new WritableStream() übergeben wird) von sich aus einen Fehler. Den Controller bekommt man als Argument in start(controller) und write(chunk, controller). Nach dem Aufruf ist der Stream dauerhaft fehlerhaft: Die Promises von writer.write(), writer.ready, writer.close() und writer.closed werden mit dem übergebenen Grund e abgelehnt. Chunks, die noch in der Warteschlange stehen, werden verworfen.

Am meisten bringt die Methode bei Fehlern, die außerhalb der Callbacks der Senke entstehen, zum Beispiel wenn eine WebSocket-Verbindung abbricht, ein Watchdog-Timer abläuft oder ein Gerät (Web Serial, Web USB) getrennt wird. Innerhalb von write() reicht es meistens, eine Ausnahme zu werfen oder ein abgelehntes Promise zurückzugeben. Auch das versetzt den Stream in den Fehlerzustand.

Der Unterschied zu WritableStream.abort() bzw. writer.abort(): abort() wird von der Seite, die schreibt, aufgerufen, controller.error() dagegen von der Senke. Deshalb wird bei error() auch kein abort()-Callback der Senke ausgelöst.

Parameter

Name Typ Default Beschreibung
$e any undefined Der Fehlergrund. Mit ihm werden später alle Promises der Schreibvorgänge abgelehnt. Am besten ein Error-Objekt (bzw. eine Unterklasse davon) übergeben, damit ein Stacktrace und eine lesbare Meldung vorhanden sind.

Rückgabewert

Typ
undefined
Beschreibung
Kein Rückgabewert. Die Wirkung ist nur am Zustand des Streams zu sehen.

Beispiele

Fehler von außen melden und Folgen für den Writer

const stream = new WritableStream({
  start(controller) {
    // Simuliert einen Verbindungsabbruch nach 100 ms
    setTimeout(() => controller.error(new Error('Verbindung verloren')), 100);
  },
  write(chunk) {
    console.log('Schreibe:', chunk);
  }
});

const main = async () => {
  const writer = stream.getWriter();
  await writer.write('A');

  await new Promise((r) => setTimeout(r, 200));

  try {
    await writer.write('B');
  } catch (err) {
    console.log('write abgelehnt:', err.message);
  }

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

main();
Schreibe: A write abgelehnt: Verbindung verloren closed abgelehnt: Verbindung verloren

WebSocket als Senke – Abbruch an den Stream weitergeben

const createSocketStream = (url) => {
  const socket = new WebSocket(url);

  return new WritableStream({
    start(controller) {
      socket.addEventListener('error', () => {
        controller.error(new Error('WebSocket-Fehler'));
      });
      socket.addEventListener('close', (ev) => {
        if (!ev.wasClean) {
          controller.error(new Error(`Verbindung unerwartet geschlossen (Code ${ev.code})`));
        }
      });
      // Erst schreiben, wenn die Verbindung steht
      return new Promise((resolve) => socket.addEventListener('open', resolve, { once: true }));
    },
    write(chunk) {
      socket.send(chunk);
    },
    close() {
      socket.close(1000);
    },
    abort() {
      socket.close(4000, 'abgebrochen');
    }
  });
};

const ws = createSocketStream('wss://echo.websocket.org');
const writer = ws.getWriter();
writer.write('Hallo Server').catch((err) => console.error(err.message));

Watchdog: Stream nach Inaktivität per error() beenden

const createWatchedSink = (timeoutMs) => {
  let timer;
  let ctrl;
  const arm = () => {
    clearTimeout(timer);
    timer = setTimeout(() => {
      ctrl.error(new Error(`Keine Daten seit ${timeoutMs} ms`));
    }, timeoutMs);
  };

  return new WritableStream({
    start(controller) {
      ctrl = controller;
      arm();
    },
    write(chunk) {
      arm();
      console.log('Empfangen:', chunk);
    },
    close() {
      clearTimeout(timer);
    }
  });
};

const main = async () => {
  const writer = createWatchedSink(50).getWriter();
  await writer.write(1);
  await new Promise((r) => setTimeout(r, 100));
  await writer.write(2).catch((err) => console.log('Fehler:', err.message));
};

main();
Empfangen: 1 Fehler: Keine Daten seit 50 ms