Signatur
Beschreibung
Mit controller.error(reason) signalisiert die Quelle eines selbst erstellten ReadableStream, dass ein nicht behebbarer Fehler aufgetreten ist, etwa ein abgebrochener Netzwerkzugriff, ungültige Daten oder eine Zeitüberschreitung. Der Controller wird in den Methoden start(), pull() und cancel() der Underlying Source übergeben.
Nach dem Aufruf befindet sich der Stream im Zustand errored. Alle Chunks, die noch in der internen Warteschlange liegen, werden sofort verworfen. Ausstehende und künftige reader.read()-Aufrufe werden mit reason abgelehnt, und auch das Promise reader.closed wird mit diesem Grund abgelehnt. Über pipeTo() oder pipeThrough() verbundene Streams geben den Fehler weiter.
Wann nimmt man error() und wann close()? close() beendet einen Stream ordnungsgemäß: Die bereits eingereihten Chunks können noch gelesen werden. error() ist für Fehlerfälle gedacht, in denen die Daten unvollständig oder unbrauchbar sind und der Konsument das auch erfahren soll. Wirft start() oder pull() eine Ausnahme oder gibt ein abgelehntes Promise zurück, ruft der Stream error() intern automatisch auf.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $reason | any | undefined | Fehlergrund, mit dem alle künftigen Interaktionen abgelehnt werden. Üblich ist ein Error-Objekt, damit ein Stacktrace vorhanden ist. Grundsätzlich ist aber jeder Wert erlaubt. |
Rückgabewert
undefined zurück.Beispiele
Einfacher Fall: Stream nach einem Chunk mit Fehler beenden
const stream = new ReadableStream({
start(controller) {
controller.enqueue('Erster Chunk');
// Fehler sofort melden – der noch eingereihte Chunk wird verworfen
controller.error(new Error('Quelle nicht erreichbar'));
}
});
const reader = stream.getReader();
try {
const { value } = await reader.read();
console.log('Gelesen:', value);
} catch (err) {
console.error('Lesefehler:', err.message);
}
Praxis: Zeitüberschreitung für eine Datenquelle
const createTimedStream = (source, timeoutMs) => {
let timer;
return new ReadableStream({
start(controller) {
const resetTimer = () => {
clearTimeout(timer);
timer = setTimeout(() => {
controller.error(new Error(`Keine Daten seit ${timeoutMs} ms`));
}, timeoutMs);
};
resetTimer();
source.on('data', (chunk) => {
resetTimer();
controller.enqueue(chunk);
});
source.on('end', () => {
clearTimeout(timer);
controller.close();
});
},
cancel() {
clearTimeout(timer);
}
});
};
// Beispielquelle, die nur einmal Daten liefert und dann verstummt
const listeners = {};
const fakeSource = { on: (evt, fn) => { listeners[evt] = fn; } };
const stream = createTimedStream(fakeSource, 500);
listeners.data('Hallo');
const reader = stream.getReader();
console.log((await reader.read()).value);
reader.read().catch((err) => console.error(err.message));
Ungültige Daten in pull() melden und über reader.closed erkennen
const values = [1, 2, 'kaputt', 4];
let index = 0;
const stream = new ReadableStream({
pull(controller) {
const value = values[index++];
if (value === undefined) return controller.close();
if (typeof value !== 'number') {
controller.error(new TypeError(`Ungültiger Wert: ${value}`));
return;
}
controller.enqueue(value);
}
});
const reader = stream.getReader();
reader.closed.catch((err) => console.log('Stream fehlerhaft:', err.message));
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
console.log('Wert:', value);
}
} catch (err) {
console.log('Abbruch:', err.name);
}
// Wichtig · Fallstricke
- Daten gehen verloren:
error()leert die interne Warteschlange sofort. Chunks, die zwar eingereiht, aber noch nicht gelesen wurden, erreicht der Konsument nicht mehr. Soll er alle Daten erhalten, verwenden Sieclose(). - Nicht umkehrbar: Ein Stream im Fehlerzustand lässt sich nicht zurücksetzen. Für einen neuen Versuch muss ein neuer Stream erzeugt werden.
- Ist der Stream bereits geschlossen oder fehlerhaft, hat ein weiterer Aufruf von
error()keine Wirkung und wirft auch keine Ausnahme.enqueue()oderclose()nacherror()werfen dagegen einenTypeError. - Übergeben Sie als
reasonmöglichst einError-Objekt. Primitive Werte erschweren die Fehlersuche, weil kein Stacktrace vorhanden ist. - Ein Fehler in einer Pipe-Kette (
pipeTo()/pipeThrough()) bricht standardmäßig auch das Ziel ab (preventAbort: false). - Für Byte-Streams (
type: 'bytes') gibt es die EntsprechungReadableByteStreamController.error(). - Kompatibilität: wird von allen modernen Browsern unterstützt. In Node.js ist die Methode über
node:stream/webverfügbar, ab Version 18 auch global.